tom@home.htb:~$

Blog o HTB

28 December 2020

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:

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ů

Co si odnést do praxe

Další související články

HTB Stroje

Techniky

Nástroje

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