Player
Úvod a kontext
Player je dlouhý, ale velmi poučný řetězec. Začíná nenápadně: web na 80/tcp vrací jen 403, ale vhost enumerace otevře několik dalších aplikací. Z nich pak postupně vypadnou záložní zdrojáky, JWT tajemství, LFI přes ffmpeg, omezený SSH přístup, další vývojářské heslo a nakonec i root přes nebezpečnou PHP deserializaci.
Právě množství mezikroků je na Playeru nejcennější. Žádná jednotlivá chyba sama o sobě nestačí. Teprve správné propojení indicií z player.htb, staging.player.htb a dev.player.htb vytvoří konzistentní cestu až k rootovi.
Počáteční průzkum
Otevřené služby
nmap -p 1-65535 -T4 -A -sC -v $IP
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.11
80/tcp open http Apache httpd 2.4.7
6686/tcp open ssh OpenSSH 7.2
Na portu 80 nebyla běžná aplikace, ale jen 403 Forbidden. To je typická situace, kdy je potřeba přestat přemýšlet o adresářích a přejít na enumeraci virtuálních hostů.
Vhosty a skrytý obsah
Přesně pro podobnou situaci má smysl Wfuzz: hlavní web vrací jen minimum, ale Host hlavička odhalí další větve aplikace, na kterých teprve leží skutečný foothold.
wfuzz -H "Host: FUZZ.player.htb" -w /usr/share/wordlists/wfuzz/general/megabeast.txt --sc 200 http://$IP
chat
dev
staging
Na player.htb pak další enumerace odhalila mimo jiné /launcher/, což byl první skutečně důležitý vstup do řetězce.
Analýza zjištění
Záložní PHP soubor a JWT tajemství
Klíčovou stopu neprozradila hlavní stránka, ale její záložní kopie. V /launcher/ šlo přes příponu ~ získat zdrojový kód PHP souboru:
To je přesně ten typ vývojového artefaktu, který řeším v článku Otevřený .git, zálohy a vývojové artefakty jako první foothold.
/launcher/dee8dc8a47256c64630d803a4c40786c.php~
Soubor obsahoval dvě zásadní informace:
$key = '_S0_R@nd0m_P@ss_';
if($decoded->access_code === "0E76658526655756207688271159624026011393")
Na stránce se zároveň vracel JWT cookie access. Jakmile byl známý shared secret i očekávaná hodnota access_code, šlo token přepodepsat a otevřít skrytý launcher bez další autentizace.
To je dobrý příklad toho, že slabina neležela v JWT jako technologii. Problém byl v tom, že aplikace sama vystavila svůj podpisový klíč v backup souboru.
Detailněji tenhle pattern rozebírám v článku JWT signing secret a claim abuse.
ffmpeg jako lokální čtečka souborů
Skrytý launcher používal ffmpeg ke zpracování médií. To otevřelo cestu ke známému HLS/file read zneužití, kdy speciálně připravený playlist přiměje backend číst lokální soubory.
Přes tuto techniku šlo vytáhnout například:
/var/www/backup/service_config
/var/www/staging/fix.php
První soubor vydal heslo pro účet telegen:
d-bC|jC!2uepS/w
V tu chvíli bylo důležité nezůstat jen u předpokladu, že správný cíl je standardní SSH na 22/tcp. Druhý SSH démon na 6686/tcp vypadal od začátku podezřeleji a ukázal se jako správný vstupní bod.
Omezený SSH přístup a další pivot
Přihlášení na port 6686 skutečně fungovalo, ale jen do lshell, tedy omezené shellové vrstvy. To ještě nestačilo na normální práci se systémem. U OpenSSH 7.2 ale dávalo smysl ověřit, zda půjde zneužít xauth injection a číst soubory i přes omezený shell:
python /usr/share/exploitdb/exploits/multiple/remote/39569.py player.htb 6686 telegen 'd-bC|jC!2uepS/w'
Tím šlo získat jak user.txt, tak i obsah /var/www/staging/fix.php, kde byly další přihlašovací údaje:
peter / CQXpm\z)G5D#%S$y=
Získání přístupu
telegen a vývojová instance
První potvrzení úspěšného pivotu přišlo právě přes čtení user flagu:
.readfile /home/telegen/user.txt
__CENSORED__
Řetězec ale pokračoval dál. Heslo peter z fix.php otevřelo přístup do vývojové instance dev.player.htb, kde běžel Codiad. Pro něj existoval funkční RCE exploit, takže další foothold už vedl k normálnímu webovému shellu jako www-data.
Jakmile bylo známé i heslo telegen, dalo se z webového shellu přepnout na plnohodnotný bash bez omezení lshell:
su -s /bin/bash telegen
Eskalace oprávnění
playBuff a nebezpečná deserializace
Lokální enumerace pomocí pspy ukázala periodicky spouštěný root proces:
/usr/bin/php /var/lib/playbuff/buff.php
Adresář /var/lib/playbuff byl z technického hlediska důležitější než běžné SUID binárky. Soubor merge.log byl zapisovatelný uživatelem telegen a buff.php pracoval s PHP třídou playBuff, jejíž __wakeup() metoda zapisovala data do souboru podle vlastností objektu:
class playBuff {
public $logFile="/var/log/playbuff/logs.txt";
public $logData="Updated";
public function __wakeup() {
file_put_contents(__DIR__."/".$this->logFile,$this->logData);
}
}
To je klasický privesc vzor: privilegovaný proces důvěřuje serializovaným datům, která může neprivilegovaný uživatel ovlivnit. Je to zároveň přímý příklad článku Insecure deserialization napříč stacky, jen tentokrát v PHP a v lokálním root workflow místo veřejného endpointu. Stačilo tedy připravit objekt playBuff tak, aby:
logFilemířil na../../../../../../root/.ssh/authorized_keys,logDataobsahoval útočníkův veřejný klíč.
Payload pak stačilo zapsat do /var/lib/playbuff/merge.log a počkat, až ho root proces zpracuje. Výsledkem byl SSH přístup jako root a následně i root.txt.
Shrnutí klíčových poznatků
- Player ukazuje, jak nebezpečné jsou kombinace zdánlivě malých chyb: záložní zdroják, JWT secret,
ffmpegfile read a reuse hesel. - Uživatelský přístup nevznikl jedním shellem, ale postupným pivotem přes
telegen,petera vývojovou instanci Codiad. - Root část nestála na kernel exploitu, ale na PHP deserializaci v pravidelně spouštěném root skriptu.
Co si odnést do praxe
- Záložní soubory jako
*.php~nebo ponechané testovací endpointy často obsahují přesně ta tajemství, která by jinak bylo obtížné získat. CI/CD i web server musí podobné artefakty blokovat. - Server-side zpracování médií pomocí
ffmpegnebo podobných nástrojů je potřeba sandboxovat. Jakmile backend čte útočníkem dodaný playlist nebo kontejner, může z něj snadno vzniknout lokální čtení souborů. - Omezený shell není obrana sám o sobě. Pokud na stejném účtu zůstane další slabina v SSH vrstvě nebo přístup k interním souborům, útočník si cestu kolem omezení najde.
- Privilegované dávkové úlohy nesmějí deserializovat nedůvěryhodná data. Jakmile root proces čte zapisovatelný log nebo frontu, je to přímý privesc kandidát.