Fatty
Úvod a kontext
Fatty je stroj, kde hlavní vstup neleží ve webu, ale v distribuovaném Java klientu. Ten je veřejně dostupný přes anonymní FTP, spoléhá na starý Java 8/TLS stack a po dekompilaci rychle ukáže, že aplikace není navržená bezpečně ani na klientské, ani na serverové straně.
Řetězec stojí na třech navazujících vrstvách. Nejdřív je potřeba klient vůbec rozchodit a porozumět jeho protokolu. Pak z interních poznámek a MITM logů vyplyne SQL injection v přihlašování. A teprve po přihlášení dává smysl stáhnout serverovou část a zneužít nebezpečnou Java deserializaci. Root část už pak není o Java exploitu, ale o klasické wildcard injection do tar v root cron jobu.
Počáteční průzkum
FTP s klientem a interními poznámkami
První nmap hned ukáže, že nejzajímavější službou není SSH, ale anonymní FTP s klientem fatty-client.jar a třemi textovými poznámkami. Současně jsou otevřené tři TLS porty 1337 až 1339, takže je zřejmé, že aplikace komunikuje mimo běžný webový protokol.
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
21/tcp open ftp vsftpd 2.0.8 or later
| ftp-anon: Anonymous FTP login allowed
| -rw-r--r-- 1 ftp ftp 15426727 Oct 30 12:10 fatty-client.jar
| -rw-r--r-- 1 ftp ftp 526 Oct 30 12:10 note.txt
| -rw-r--r-- 1 ftp ftp 426 Oct 30 12:10 note2.txt
| -rw-r--r-- 1 ftp ftp 194 Oct 30 12:10 note3.txt
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u7 (protocol 2.0)
1337/tcp open ssl/waste?
1338/tcp open ssl/wmc-log-svc?
1339/tcp open ssl/kjtsiteserver?
Poznámky samy o sobě prozradí tři důležité věci: server byl přesunut z 8000 na 1337, klient pořád vyžaduje Java 8 a dočasné přihlašovací údaje jsou qtc / clarabibi.
Rozchození klienta a TLS proxy
Klient po stažení nejde jen spustit. Je potřeba mu upravit cílový port, použít Java 8 a přizpůsobit se starému TLS nastavení. sslscan ukáže jen TLSv1.0 a cipher AES128-SHA, takže běžné moderní proxy selhávají, pokud se výslovně nepřepnou do kompatibilního režimu.
update-alternatives --config java
sslscan 10.10.10.174:1337
=> Accepted TLSv1.0 128 bits AES128-SHA
Po dekompilaci klienta navíc vyjde najevo, že TrustedFatty.java pracuje s klientským certifikátem fatty.p12 chráněným heslem secureclarabibi123. To dovolí certifikát rozbalit a postavit MITM přes sslsplit, takže je možné číst vlastní aplikační protokol.
openssl pkcs12 -in fatty.p12 -nocerts -out fatty.key
openssl pkcs12 -in fatty.p12 -clcerts -nokeys -out fatty.crt
sslsplit -k fatty.key -c fatty.crt -Z -D -P -L con.log -r tls10 -s AES128-SHA ssl 127.0.0.1 8000 10.10.10.174 1339
Analýza zjištění
Co prozradí MITM log
MITM zde není samoúčelné. Log ukáže nejen úspěšné přihlášení qtc, ale i strukturu interního úložiště notes a mail. V security.txt je zmínka o proběhlém penetračním testu a v dave.txt ještě důležitější informace: administrátorské účty byly kvůli bezpečnostním problémům odstraněné a proti loginu přibyl timeout, aby se zhoršily time-based SQL injection útoky.
To je silná indicie, že chyba v autentizaci stále existuje, jen už nejde zneužít nejjednodušším způsobem. Přesně proto dává smysl testovat klasické login bypass payloady místo slepého fuzzingu celého protokolu.
Login bypass a server-side deserializace
Payload qtc' or '1'='1' or ''=' v logu vede k úspěšnému přihlášení, takže SQL injection ve vstupu pro login je potvrzená. Tím se otevře přístup do klienta a k serverovým artefaktům. Jakmile je k dispozici serverová část aplikace, je vidět i druhá zásadní chyba: funkce changePw deserializuje objekt ClientCredential bez bezpečnostních omezení.
To mění způsob práce. Místo dalšího lámání SQLi už dává smysl připravit serializovaný payload přes ysoserial a poslat ho přes rutinu pro změnu hesla. Po úpravě objektu tak, aby se tvářil jako požadavek skupiny admins, server payload zpracuje a spustí příkaz pro reverzní shell.
Získání přístupu
Shell jako qtc
Po doručení serializovaného payloadu do changePw vznikne shell jako qtc. Důležitější než samotný shell je tady to, proč fungoval: SQL injection jen otevřela dveře do aplikace, ale skutečnou RCE přinesla až deserializace neověřeného objektu na serveru.
Eskalace oprávnění
Wildcard injection do root záloh
Lokální eskalace už nemá s Javou nic společného. Root cron job pravidelně vytváří zálohy přes tar nad obsahem, který může qtc ovlivnit. To je klasický scénář pro wildcard injection: pokud se v archivovaném adresáři objeví soubory pojmenované jako parametry tar, root je při dalším běhu interpretuje jako volby.
V praxi stačí připravit shell skript a k němu soubory, které zneužijí checkpoint mechaniku tar. Při dalším běhu cron se shell skript spustí s root právy a otevře finální shell.
Shrnutí klíčových poznatků
- Fatty je především o správné analýze klienta. Bez rozchození Java 8 prostředí, TLS proxy a dekompilace by se k podstatě problému vůbec nešlo dostat.
- SQL injection v loginu byla důležitá, ale sama o sobě nestačila k RCE. Skutečný průlom přineslo až pochopení server-side deserializace v
changePw. - Root část dobře ukazuje, že i po čistě aplikačním footholdu často rozhodne obyčejná lokální automatizace, tady konkrétně nebezpečné použití
tarv root cron jobu.
Co si odnést do praxe
- Distribuovaný klient není bezpečnější jen proto, že nejde o web. Pokud je veřejně ke stažení, musí se počítat s dekompilací, reverzní analýzou i s tím, že všechny embedded certifikáty a hesla nakonec někdo vytáhne.
- Java deserializace neověřených objektů je opakovaně katastrofální návrhová chyba. Fatty ukazuje, že jakmile server slepě přijímá serializovaný objekt od klienta, je jen otázka času, kdy to skončí RCE.
- Privilegované zálohovací joby nesmějí běžet nad uživatelsky ovlivnitelným obsahem bez tvrdé kontroly vstupů. Wildcard injection do
tarje stará technika, ale v praxi stále funguje přesně tam, kde administrativní skripty předpokládají důvěryhodné soubory.