Friday, October 19, 2012
How to check your browser for security?
Friday, August 3, 2012
Use GET to POST form to some ASP.NET application
During one security assessment of an ASP.NET application, I find that it is possible to use "GET" requests to POST form data to the ASP.NET application. The application processes those form elements the same way as it is processing "POST" request. The web server logs those requests as "GET" requests instead of "POST" requests. This makes it convenient for the attackers to hide their attacks.
Here is a sample application:
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
var forms = HttpContext.Current.Request.Form;
foreach (String s in forms.AllKeys)
{
sb.Append(string.Format("{0} => {1}", s, forms[s]));
sb.Append("
");
}
lblStatus.Text = sb.ToString();
}
The application is using HttpContext.Current.Request.Form to retrieve form element value. According to the documentation of MSDN (http://msdn.microsoft.com/en-us/library/system.web.httprequest.form),
The Form property is populated when the HTTP request Content-Type value is either "application/x-www-form-urlencoded" or "multipart/form-data".
As long as Content-Type value is either "application/x-www-form-urlencoded" or "multipart/form-data", the Form property is populated no matter whatever method the request is sent.
Here is one GET request with Content-Type and Content-Length headers:
Thursday, June 7, 2012
Wednesday, May 16, 2012
Same Origin Policy for Document Object Model
- Domain name (for example, www.example.com)
- Application protocol (for example, http or https)
- Port number (for example, 80 or 8080)
- Changing document.domain
- Use postMessage of HTML5
Tuesday, May 15, 2012
Different formats for RSA keys
- DER format is based on Abstract Syntax Notation One (ASN.1). You can use ASN.1 Editor to view its structure and contents.
- PEM format from OpenSSL is based64 encoded format of DER format
- PRIVATEKEYBLOB and PUBLICKEYBLOB are C-style structure defined by Microsoft.
Thursday, May 10, 2012
Use pcapy and impacket to interact with libpcap in Python
The first step is to install them on my Windows box. I tried easy_install and it stopped due to an error of "not being able to find pcap.h". To fix the problem, I downloaded the latest winpacp developer's pack from http://www.winpcap.org/devel.htm. After unzipping the content to the same directory that cl.exe looks for, everything went well. There is no problem with installing impacket using easy_install.
The second step is to write a simple script to read some TCP packets from one network interface. Here is my readLivePacket.py:
from pcapy import findalldevs,open_live
from impacket import ImpactDecoder, ImpactPacket
devices = findalldevs();
pc = open_live(devices[1], 2048, False, 1000)
pc.setfilter('tcp')
def processPacket(hdr, data):
decoder = ImpactDecoder.EthDecoder()
packet=decoder.decode(data)
ippacket=packet.child()
tcppacket=packet.child()
print tcppacket
packet_limit = -1
pc.loop(packet_limit, processPacket)
I also want my script to read and analyze packets from pcap file. Here is my readPacketFile.py:
from pcapy import findalldevs,open_offline
from impacket import ImpactDecoder, ImpactPacket
fileName="c:\\temp\\rsa\\test.pcap"
pc = open_offline(fileName)
pc.setfilter('tcp')
def processPacket(hdr, data):
decoder = ImpactDecoder.EthDecoder()
packet=decoder.decode(data)
ippacket=packet.child()
tcppacket=packet.child()
print tcppacket
packet_limit = -1
pc.loop(packet_limit, processPacket)
pcapy and impacket make the job of analyzing network traffic easy for Python.
Tuesday, May 8, 2012
OWASP 2012 Online Competition
I spent 8 hours on 05/02/2012 and solved all challenges. Here are my solutions to the challenges:
- 8018 OWASP Hackademic Challenge 1. There is an unusual element on the source code of the page: YXBwc2VjX3VzYTp0aGlzZWFz this is base64 encoding of appsec_usa:thiseas. That's the user name and password for the portal.
- 8019 OWASP Hackademic Challenge 2. The goal is to find the password to the website. However, the website hides its password within JavaScript as shown below. I just used FireBug and found the password: "take a break"
- 8020 OWASP Hackademic Challenge 3. The goal is to test XSS issue and generate a alert box with the message of "XSS!". Unfortunately, it seems that the challenge is only a string matching XSS problem. The matching string is <script> alert('XSS!'); </script>
- 8021 OWASP Hackademic Challenge 4. This challenge is just a variation of challenge 3 with same goal. The matching string is: <script> alert(String.fromCharCode(88,83,83,33)); </script>
- 8022 OWASP Hackademic Challenge 5. The goal is to access the hidden content with their special web browser. The answer is to change user agent of web browser: User-Agent: p0wnBrowser version 2.30
- 8023 OWASP Hackademic Challenge 6. The goal is to find the password to access the website. The password is hidden into JavaScript again. The JavaScript can be obtained by using Firebug and JavaScriptShell. The password is: h@ckers!
- 8024 OWASP Hackademic Challenge 7. The goal is to gain admin access to the website. After spidering the website, I find an interesting file http://hackademics.hacking-lab.com/ch007/index_files/lastlogin.log. Here is its content:
- 8025 OWASP Hackademic Challenge 8. The goal is to access the website as admin. The backdoor shell only support these commands: ls,whoami,id,help,su. If su is typed, the shell asks for user name and password. I also noticed that there is an interesting image file found by using "ls" command: http://hackademics.hacking-lab.com/ch008/4admin0Nly.jpg. It is not a normal JPG image file. Its content is:
2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 20 55 73 65 72 6e 61 6d 65 3a 20 73 75 70 65 72 61 64 6d 69 6e 20 50 61 73 73 77 6f 72 64 3a 20 30 77 40 73 70 55 53 41 79 30 20 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d
The ascii values of its contents contains: Username: superadmin Password: 0w@spUSAy0 - 8026 OWASP Hackademic Challenge 9. The goal is to gain admin access to the website.
1) Change the user agent of the browser to use
2) The shell is accessible from http://hackademics.hacking-lab.com/ch009/y0_man_y0.php
3) Use "ls" command and find some interesting pages: adminpanel.php, y0_man_y0.php, log.history.php
4) In the source code of http://hackademics.hacking-lab.com/ch009/log.history.php, there is some interesting comments:slrig_$$ap_$GN0RTS_4_s1_s1Ht :drowssap nimda :emanresu
Decode the comment and reverse the order, I get the following message:
'username: admin password: tH1s_1s_4_STR0NG$_pa$$_girls'
5) Use the above user name and password to log in the admin panel page.
- 8027 OWASP Hackademic Challenge 10. The goal is to gain access to the website.
1) There is a hidden field called LetMeIn=False. I changed it LetMeIn=True and accessed the website.
2) The alert function looks like
alert("01010011 01100101 01110010 01101001 01100001 01101100 00100000 01001110 01110101 01101101 01100010 01100101 01110010 00111010 00100000 01010100 01001000 01001001 01010011 00101101 01001001 01010011 01001111 01000100 01000100 00101101 01000011 01000001 01010101 01010011 01000101 00101101 01001001 01000001 01001101 01000001 00101101 01010011 01010101 01010000 01000001 00101101 01001000 01000001 01000011 01001011 01000001 ")
A simple python script can decode this as THIS-ISODD-CAUSE-IAMA-SUPA-HACKA
3) Enter this code and mission accomplished.- 7019 AES Bit-Flipping Attack. The goal is to regenerate a valid ticket based on an expired AES CBC encrypted ticket: B60086CD1E68CEF25BC1BEC429D8F3C01D45F0196331DA5012B99067A25463A493CCBF690FD88F850BD5273C5A7D72B6
1) Burp is a perfect tool to automate this attack. Burp Intrude has bit flipper built-in.
2) There are lots of valid tickets generated by Burp. One example is:
60086CD1E68CEF25BC1BEC429D8F3C01D45F0196331DA5012B99063A25463A493CCBF690FD88F850BD5273C5A7D72B6
And here is the result from server:
Hello hacker10 (email: You've logged-in successfully
Ticket valid until: 20141011
Solution code: X678RWER_HAXXOR- 2312 Blind SQL injection. The goal is to write a small program to read the email address of the customer “Franziska Knobel” through
blind SQL injection.
1) The email address is hacker30@hack.er
2) This python script was written in short time just for solve the problem as soon as possible:- 2313 Time Based Blind SQL Injection. The goal is to write a small program to read the phone number of"Sandra Fischer” using time based blind SQL Injection.
1) The phone number is 072544558822) This python script was written in short time just for solve the problem as soon as possible. - 8027 OWASP Hackademic Challenge 10. The goal is to gain access to the website.
function GetPassInfo(){ | |
var madhouuuuuuuseeee = "givesacountinatobp laryk" | |
var j = madhouuuuuuuseeee.charAt(1); var h = madhouuuuuuuseeee.charAt(0); var l = madhouuuuuuuseeee.charAt(17); | |
var g = madhouuuuuuuseeee.charAt(2); var i = madhouuuuuuuseeee.charAt(6); var x = madhouuuuuuuseeee.charAt(18); | |
var l = madhouuuuuuuseeee.charAt(3); var p = madhouuuuuuuseeee.charAt(2); var m = madhouuuuuuuseeee.charAt(20); | |
var s = madhouuuuuuuseeee.charAt(17); var k = madhouuuuuuuseeee.charAt(10); var d = madhouuuuuuuseeee.charAt(3); | |
var bb = madhouuuuuuuseeee.charAt(6); var d = madhouuuuuuuseeee.charAt(13); var r = madhouuuuuuuseeee.charAt(8); | |
var a = madhouuuuuuuseeee.charAt(0); var d = madhouuuuuuuseeee.charAt(3); var r = madhouuuuuuuseeee.charAt(16); | |
var b = madhouuuuuuuseeee.charAt(1); var e = madhouuuuuuuseeee.charAt(4); var j = madhouuuuuuuseeee.charAt(9); | |
var c = madhouuuuuuuseeee.charAt(2); var f = madhouuuuuuuseeee.charAt(5); var g = madhouuuuuuuseeee.charAt(4); | |
var j = madhouuuuuuuseeee.charAt(9); var h = madhouuuuuuuseeee.charAt(6); var l = madhouuuuuuuseeee.charAt(11); | |
var g = madhouuuuuuuseeee.charAt(4); var i = madhouuuuuuuseeee.charAt(7); var x = madhouuuuuuuseeee.charAt(21); | |
var l = madhouuuuuuuseeee.charAt(11); var p = madhouuuuuuuseeee.charAt(4); var m = madhouuuuuuuseeee.charAt(4); | |
var s = madhouuuuuuuseeee.charAt(17); var k = madhouuuuuuuseeee.charAt(10); var d = madhouuuuuuuseeee.charAt(3); | |
var t = madhouuuuuuuseeee.charAt(18); var n = madhouuuuuuuseeee.charAt(12); var e = madhouuuuuuuseeee.charAt(4); | |
var a = madhouuuuuuuseeee.charAt(0); var o = madhouuuuuuuseeee.charAt(13); var f = madhouuuuuuuseeee.charAt(5); | |
var b = madhouuuuuuuseeee.charAt(1); var q = madhouuuuuuuseeee.charAt(15); var h = madhouuuuuuuseeee.charAt(6); | |
var c = madhouuuuuuuseeee.charAt(2); var h = madhouuuuuuuseeee.charAt(6); var i = madhouuuuuuuseeee.charAt(7); | |
var j = madhouuuuuuuseeee.charAt(9); var i = madhouuuuuuuseeee.charAt(7); var y = madhouuuuuuuseeee.charAt(22); | |
var g = madhouuuuuuuseeee.charAt(4); var p = madhouuuuuuuseeee.charAt(4); var yy = madhouuuuuuuseeee.charAt(23); | |
var l = madhouuuuuuuseeee.charAt(11); var k = madhouuuuuuuseeee.charAt(10); var bb = madhouuuuuuuseeee.charAt(14); | |
var q = madhouuuuuuuseeee.charAt(20); var n = madhouuuuuuuseeee.charAt(12); | |
var m = madhouuuuuuuseeee.charAt(4); var o = madhouuuuuuuseeee.charAt(13); | |
var p = madhouuuuuuuseeee.charAt(4) | |
var Wrong = (bb+""+q+""+yy+""+d+""+t+""+f+""+t+""+r+""+x+""+d+""+f+""+yy) | |
if (document.forms[0].Password1.value == Wrong) | |
location.href="index.php?Result=" + Wrong; | |
} | |
30 31 30 30 31 31 30 30 20 30 31 31 30 30 30 30 31 20 30 31 31 31 30 30 31 31 20 30 31 31 31 30 31 30 30 20 30 30 31 30 30 30 30 30 20 30 31 30 30 31 31 30 30 20 30 31 31 30 31 31 31 31 20 30 31 31 30 30 31 31 31 20 30 31 31 30 31 30 30 31 20 30 31 31 30 31 31 31 30 20 30 30 31 30 30 30 30 30 20 30 31 31 30 30 30 31 30 20 30 31 31 31 31 30 30 31 20 30 30 31 31 31 30 31 30 20 30 30 31 30 30 30 30 30 20 30 31 30 30 30 30 30 31 20 30 31 31 30 31 31 30 30 20 30 31 31 30 31 30 30 31 20 30 31 31 30 30 30 31 31 20 30 31 31 30 30 31 30 31 20 30 30 31 30 30 30 30 30 20 30 31 30 31 30 30 30 30 20 30 31 31 31 30 30 31 30 20 30 31 31 30 30 31 30 31 20 30 31 31 31 30 31 30 30 20 30 31 31 31 30 31 30 30 20 30 31 31 31 31 30 30 31 20 30 30 31 30 31 31 30 30 20 30 30 31 30 30 30 30 30 20 30 31 31 31 30 31 30 31 20 30 31 31 31 30 30 31 31 20 30 31 31 30 30 31 30 31 20 30 31 31 31 30 30 31 30 20 30 31 31 30 31 31 31 30 20 30 31 31 30 30 30 30 31 20 30 31 31 30 31 31 30 31 20 30 31 31 30 30 31 30 31 20 30 30 31 31 31 30 31 30 20 30 30 31 30 30 30 30 30 20 30 31 30 30 30 30 30 31 20 30 31 31 30 31 31 30 30 20 30 31 31 30 31 30 30 31 20 30 31 31 30 30 30 31 31 20 30 31 31 30 30 31 30 31 20 30 30 31 30 30 30 30 30 20 30 31 31 30 30 30 30 31 20 30 31 31 31 30 31 30 30 20 30 30 31 30 30 30 30 30 20 30 30 31 31 30 30 30 31 20 30 30 31 31 30 31 30 30 20 30 30 31 30 31 31 31 31 20 30 30 31 31 30 30 31 31 20 30 30 31 30 31 31 31 31 20 30 30 31 31 30 30 31 30 20 30 30 31 31 30 30 30 30 20 30 30 31 31 30 30 30 31 20 30 30 31 31 30 30 30 31 20 30 30 31 30 30 30 30 30 20 30 30 31 31 30 30 30 31 20 30 30 31 31 30 30 30 30 20 30 30 31 31 31 30 31 30 20 30 30 31 31 30 31 30 31 20 30 30 31 31 31 30 30 31 20 30 30 31 31 31 30 31 30 20 30 30 31 31 30 30 30 30 20 30 30 31 31 30 30 30 30 20 30 31 31 30 30 30 30 31 20 30 31 31 30 31 31 30
It looks like ASCII code in binary format after changing 30 to 0 and 31 to 1 and 20 to separator. A simple Python script decodes its content as:
Last Login by: Alice Pretty, username: Alice at 14/3/2011 10:59:00am
Now, we have an user name "Alice" which can be used to access the website. I noticed that the session id remained same for different sessions of Alice. The session id is 64489c85dc2fe0787b85cd87214b3810.0 The first part looks like md5. 64489c85dc2fe0787b85cd87214b3810=md5(Alice). OK, I just need to generate a new session token for admin. After several attempts, the system accepts this cookie: e3afed0047b08059d0fada10f400c1e5.1
where md5(Admin) = e3afed0047b08059d0fada10f400c1e5
Thursday, April 19, 2012
SQL injection by truncation
This is an old attack technique. More details can be found at
http://msdn.microsoft.com/en-us/magazine/cc163523.aspx
https://www.blackhat.com/presentations/bh-usa-06/BH-US-06-Neerumalla.pdf
The question is “If I use quotename() or replace() or wrap all my SQL parameters, are my dynamic SQL statements still subject to SQL injection?”
Even with quotename() or replace(), your dynamic SQL statements might be vulnerable to SQL injections due to truncations if you make these mistakes:
- The dynamics SQL is assigned to a variable whose buffer is not large enough. An attacker can force truncation by passing unexpectedly long strings to your stored procedure.
- The results returned by quotename() or replace() are saved into local variables whose buffer are not large enough. Those returned strings are truncated. An attacker can manipulate it to his advantages.
Here is the example showing truncation problems:
CREATE PROCEDURE sp_MySetPassword
@loginname varchar(128),
@old varchar(200),
@new varchar(128),
AS
DECLARE @login sysname
DECLARE @newpassword sysname
DECLARE @oldpassword sysname
-- the data stored in command might be truncated because its small size
DECLARE @command varchar(200)
-- the data stored in those temp variables might be truncated becuase
-- quotename() can return up to 258 characters and replace() can return up to 400 characters
SET @login = QUOTENAME(@loginname, '''')
SET @oldpassword = REPLACE(@old, '''', '''''')
SET @newpassword = QUOTENAME(@new, '''')
SET @command = 'UPDATE Users set password = ' + @newpassword
+ ' where username =' + @login + ' AND password = ' + @oldpassword;
EXEC (@command)
To avoid truncation issues, the best approach is to use parameterized queries in your stored procedures. If you must use quotename() or replace(), you can address those two issues: i) use a large buffer for the command variable or directly execute the dynamic T-SQL. ii) use large buffers for those temporary variables or call quotename() or replace() directly in dynamic SQL statement.
The above example can be fixed like this:
CREATE PROCEDURE sp_MySetPassword
@loginname varchar(128),
@old varchar(200),
@new varchar(128),
AS
DECLARE @command varchar(3000)
SET @command = 'UPDATE Users set password = ' + QUOTENAME(@new, '''')
+ ' where username =' + QUOTENAME(@loginname, '''') + ' AND password = ' + REPLACE(@old, '''', '''''');
EXEC (@command)
Tuesday, April 17, 2012
Search Engine Security for Google Chrome?
Business logic Abuse for Nordstrom
Wednesday, March 14, 2012
Set up your environment for security testing
If you do not have any old Windows XP CD, you can try to download the Federal Desktop Core configuration (FDCC) image from NIST.
For Windows XP, here are the download links:
http://nvd.nist.gov/download/FDCC-Q4-2009/FDCC_IMAGES/XP-Q4-2009/XP_NIST_FDCC_Q4_2009.zip
http://nvd.nist.gov/download/FDCC-Q4-2009/FDCC_IMAGES/XP-Q4-2009/XP_NIST_FDCC_Q4_2009.z01
http://nvd.nist.gov/download/FDCC-Q4-2009/FDCC_IMAGES/XP-Q4-2009/XP_NIST_FDCC_Q4_2009.z02
http://nvd.nist.gov/download/FDCC-Q4-2009/FDCC_IMAGES/XP-Q4-2009/XP_NIST_FDCC_Q4_2009.z03
The username / password scheme for the Image is:
Renamed_Admin / P@ssw0rd123456
http://www.offensive-security.com/metasploit-unleashed/Metasploitable
Metasploitable is a VMware based virtual machine running Ubuntu 8.04 server. A number of vulnerable services have been included, some of which are an install of tomcat 5.5 (with weak credentials), distcc, tikiwiki, twiki, and an older version of mysql server.
http://think-security.com/metasploitable-your-first-training-ground/
Here are some of the credentials that you can use to access it:
msfadmin:msfadmin
user:user
service:service
postgres:postgres
klog:123456789
Wednesday, March 7, 2012
Penetration Testing Execution Standard
- Pre-engagement Interactions
- Intelligence Gathering
- Threat Modeling
- Vulnerability Analysis
- Exploitation
- Post Exploitation
- Reporting
Tuesday, March 6, 2012
Some links for log4net
http://www.beefycode.com/post/Log4Net-Tutorial-pt-1-Getting-Started.aspx
http://www.beefycode.com/post/Log4Net-Tutorial-pt-2-Basic-XML-Configuration.aspx
http://www.beefycode.com/post/Log4Net-Tutorial-pt-3-Appenders.aspx
http://www.beefycode.com/post/Log4Net-Tutorial-pt-4-Layouts-and-Patterns.aspx
http://www.beefycode.com/post/Log4Net-Tutorial-pt-5-Using-Logger-Objects.aspx
http://www.beefycode.com/post/Log4Net-Tutorial-pt-6-Log-Event-Context.aspx
http://www.beefycode.com/post/Log4Net-Tutorial-pt-7-Filters.aspx
http://www.beefycode.com/post/Log4Net-Tutorial-pt-8-Lossy-Logging.aspx
http://www.beefycode.com/post/Log4Net-Recommended-Practices-pt-1-Your-Code.aspx
http://www.beefycode.com/post/Death-By-Logging-1-Logs-Consume-Space.aspx
http://actcode.com/2009/11/net-application-logging-with-log4net-in-console-file-database/
Year of Security for Java by John Melton
John Melton wrote some wonderful stuff about Java security
Year of Security for Java – Week 1 - Session Fixation Prevention
Year of Security for Java – Week 2 – Error Handling in web.xml
Year of Security for Java – Week 3 – Session Cookie Secure Flag
Year of Security for Java – Week 4 – Session Cookie HttpOnly Flag
Year of Security for Java – Week 5 – Clickjacking Prevention
Year of Security for Java – Week 6 – CSRF Prevention in Java
Year of Security for Java – Week 7 – Content Security Policy
Year of Security for Java – Week 8 – HTTP Strict Transport Security
OWASP Top 10
OWASP Top 10 focuses on identifying the most serious risks for your application.
https://www.owasp.org/index.php/Top_10_2010-Main
Troy Hunt writes excellent “OWASP TOP 10 for .NET”
1. Injection
3. Broken Authentication and Session Management
4. Insecure Direct Object References
5. Cross-Site Request Forgery (CSRF)
7. Insecure Cryptographic Storage
8. Failure to Restrict URL Access
9. Insufficient Transport Layer Protection
10. Unvalidated Redirects and Forwards
Here are some other interesting links related with owasp top 10
http://resources.infosecinstitute.com/owasp-top-10-tools-and-tactics/
Friday, March 2, 2012
Hide some server response headers
Troy Hunt talks about “Don’t let your response headers talk too loudly”
There are four headers that might leak information about the servers:
- Server: The web server software being run by the site. Typical examples include “Microsoft-IIS/7.5”, “nginx/1.0.11” and “Apache”.
Solution: The easiest way is to install urlScan. Find the “RemoveServerHeader” setting with its configuration file UrlScan.ini and configure it to be “1”.
- X-Powered-By: The collection (there can be multiple) of application frameworks being run by the site. Typical examples include: “ASP.NET”, “PHP/5.2.17” and “UrlRewriter.NET 2.0.0”.
Solution: Go to IIS configuration of the website and locate “HTTP Reponse Headers” item and remove “X-Powered-By”.
- X-AspNet-Version: Obviously an ASP.NET only header, typical examples include “2.0.50727”, “4.0.30319” and “1.1.4322”.
Solution: Modify web.config
<system.web>
<httpRuntime enableVersionHeader="false" />
system.web>
- X-AspNetMvc-Version: Again, you’ll only see this in the ASP.NET stack and typical examples include “3.0”, “2.0” and “1.0”.
Solution: In Global.asax and add this to handle Application_Start event
MvcHandler.DisableMvcResponseHeader = true;
Troy also adds this function into his http://asafaweb.com/
Thursday, March 1, 2012
RSA 2012 #sophospuzzle
Came across this puzzle today at
It looks like an interesting problem. The first step is to copy and paste the c program into a text editor:
#include~!int~putchar(int~c);char~*m="noncen.cmh/alu/puyxs.hrhb\xd\xa";void~main(int~argc,char~**argv){if(argc>1&&strlen(argv[1])==8){int~i=0;while(*m){putchar(*m+(*m<0x41?0:argv[1][(++i>8?i=1:i)-1]-0x61));m++;};};}
After some minor twisting, it can be compiled successfully. It accepts input with length of eight. Let's try abcdefgh, the output is nppfis.ith/bnx/tzs.itkf
Let's take a close look at the source code, it looks like a simple encoding between command line parameter and a constant string "noncen.cmh/alu/puyxs.hrhb\xd\xa". Any character with ASCII value less than 0x41 will be unchanged. The list should include "./". Since the puzzle is from sophos.com. The best guess is that noncen.cmh will be encoded as "sophos.com". A couple of trials shows that this is the right path. Here is the so-called password:
./test2 facfkfac
sophos.com/anz/zzyzx.html
The instructions for the second step comes from http://www.sophos.com/anz/zzyzx.html
The DECODEME fashion test
Take the text of an RFC - call it RFC x. Append the eight-character password from the previous stage of the puzzle. Append the text of some other RFC - call it RFC y. (For what it's worth, x and y are different.)
The data lump you've just created will have this MD5:
01b9e8adf4dd660c7e4cb6dd8a304691
Now, compute the product of x and y, and find the smallest integer greater than xy which has exactly two prime factors.
Email the larger of these prime factors to:
duck@sophos.com
before 3pm San Francisco time on Thursday 01 March 2012. (That's 2012-03-01T15:00-5.)
You will be entered in a draw to win a NERF N-STRIKE Vulcan EBF-25.
If you are at the RSA 2012 conference, you have extra chances to win! Wear the puzzle shirt and be on the Sophos booth (#1817) at 2.10pm on Tuesday, Wednesday and Thursday. For further details, check out Naked Security.
You can follow Paul Ducklin and the puzzle on Twitter. Look for the hashtag #sophospuzzle.
Of course, you can also stop by the Sophos Booth (#1817) whenever you like to ask for advice. You never know – you might catch one of us in an unguarded moment.
The problem is to find two RFCs which contents combined with the password (facfkfac) generate a md5 hash value of (01b9e8adf4dd660c7e4cb6dd8a304691). How many RFCs are there? According to http://www.rfc-editor.org/rfc-index2.html, there are 6557 RFCs. Let's download them to local machine using Curl.
curl -o "rfc#1.txt" http://www.ietf.org/rfc/rfc[1-6557].txt
Next, a python script is created to calculate md5 sum from rfcx.txt+password+rfcy.txt. The script stops when a match is found. However, this approached turned out non-working. There are no matching MD5 found. The only explanation is that those RFC text are not exactly same as those used by puzzle creator. Another approach is tried, all RFC texts can be downloaded from ftp://ftp.rfc-editor.org/in-notes/tar/RFC-all.zip
A quick comparison between rfc1.txt from two approaches shows: rfc1.txt from curl has length of 21088 with md5 hash (99c9bdf9b63044f27de4fa8ac8ccba38). However, rfc1.txt from ftp approach has length of 21707 with md5 hash (ee350c347a17f0b46564c113667be323).
The same python script runs against new rfc text files and a match is found:
6533
6532
6531
6530
6529
6528
*****Matched***** (6528, 6533) => 01b9e8adf4dd660c7e4cb6dd8a304691
Bingo! Now, we have two numbers 6528 and 6533. Their product is 42647424. The last hurdle is to find the smallest number which is bigger and have only two prime factors.
Google search found a decent solution at http://stackoverflow.com/questions/171765/what-is-the-best-way-to-get-all-the-divisors-of-a-number
A simple modification turns out the magic number is
42647426
[1, 2, 21323713, 42647426]
The larger prime factor is 21323713. Puzzle solved. Now, it is time for a NERF Gun which I do not think that I have any chance.
Lesson learned:
It is better practice to open files using binary mode for calculation of md5 hash. Different hashes are generated for text mode and binary mode.