Outils d'utilisateurs

Outils du Site


ndh2k12_public:crypto:warcrypt

Table des matières

Warcrypt

Overview

On a accès à une page web. Il faut jouer contre un bot qui visiblement cheat.

Résolution

On se rend vite compte que la vérification de qui gagne se fait par une requête ajax.

function send() {
	var ajax = $.ajax({
		type: "POST",
		url: "ajax/send.php",
		data: "card="+$('.card:last').attr("alt")+"&sign="+$('.card:last').attr("id")
	});
	ajax.done(function(rep) {
		$('.card > img:last').remove();
		var json = eval('(' + rep +')'); 
		$('#score').html('Score : ' + json.score);
		$('.cheater_card').html('<img alt="'+json.adv_card+'" src="img/'+json.adv_card+'.png">');
		if ($('.card > img').length == 0) {
			$(location).attr('href','end.php');
		}
		$('.resultat').html(json.msg);
	});
}

Chaque carte possède un token pour la valider côté serveur. On remarque assez facilement que ce token est généré en fonction du nom de la carte. Par exemple, le token du 5 de coeur est NHGrjegtFmHu2, son nom est 05HEART.

php > var_dump(crypt("05HEART","NH"));
string(13) "NHGrjegtFmHu2"

Il nous faut trouver une carte qui pourrait battre l'as de pique du bot. Lorsqu'on envoie n'importe quoi comme nom de carte, on a comme réponse {“msg”:“Error : Unknown card”}. Il y a donc une vérification sur le nom de la carte avant de vérifier le token.

La carte qui viendrait à l’esprit de tout le monde est bien évidemment le Joker. On met JOKER comme nom de carte et on reçoit comme réponse {“msg”:“Error : sign not match”}. Nice, la carte que l'on cherche est bien JOKER !

php > var_dump(crypt("JOKER","NH"));
string(13) "NHMTkwCoDsRC6"

On renvois la requête qui va bien

POST /ajax/send.php HTTP/1.1
Host: 109.232.238.5:8001
User-Agent: Mozilla/5.0 Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: PHPSESSID=2sk41kuhqosdg27ikft6j2h0a3
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
card=JOKER&sign=NHMTkwCoDsRC6

Et … on choppe un {“msg”:“Error : sign not match”}

Si c'est pas le bon token, c'est que des caractères ont été rajoutés à la fin de JOKER. On remarque que l'on peut ajouter autant de caractère que l'on veut derrière une carte classique, le token sera toujours le bon. La taille des noms des cartes classiques sont tous de la même taille : 7 chars. JOKER fait que 5 chars! Donc 2 chars ont été rajoutés derrière! Il ne nous reste plus qu'à tester toutes les possibilités :-) (pour cela, python!)

#!/usr/bin/env python
# encoding: utf-8
 
import sys
import httplib
from crypt import crypt
 
def main():
 
    headers = {"Cookie":"PHPSESSID=2sk41kuhqosdg27ikft6j2h0a3;",
                "Content-Type":"application/x-www-form-urlencoded"}
 
    card = "JOKER"
 
    for char1 in range(31,127):
        for char2 in range(31,127):
            conn = httplib.HTTPConnection("109.232.238.5:8001")
            conn.request("POST","/ajax/send.php","card={card}&sign={0}".format(crypt(card+chr(char1)+chr(char2),"NH"),card=card),headers)
            rep = conn.getresponse()
            html = rep.read()
            if html.count("Error") < 1:
                print crypt("JOKER"+chr(char1)+chr(char2),"NH")
                print chr(char1)+chr(char2)
                print char1, char2
                sys.exit(0)
            else:
                print html
                print chr(char1)+chr(char2)
 
 
if __name__ == '__main__':
    main()
$ ./warcrypt.py
{"msg":"Error : sign not match"}
  
...
{"msg":"Error : sign not match"}
EP
...
NH3J7Hldb9sQg
P4

Well! Les deux caractères ajoutés après JOKER sont P4 ! On se débrouille pour avoir un score de 27 (27 cartes gagnées) et on se rend sur end.php (redirection automatique normalement) et on choppe le flag :-) WIN the flag is H0UR4P0URL3C4SS0UL3T

On valide avec md5(“H0UR4P0URL3C4SS0UL3T”) = 9b808110b3986a27019f2e153998e1e6

ndh2k12_public/crypto/warcrypt.txt · Dernière modification: 2017/04/09 15:33 (modification externe)