tom@home.htb:~$

Blog o HTB

7 December 2020

SUID/GTFOBins a netypické binárky

Úvod a kontext

SUID audit se často redukuje na krátký checklist: najdi find, vim, nmap, porovnej výstup s GTFOBins a zkus známý trik. To je užitečné pro rychlý screening, ale nestačí to pro skutečné posouzení rizika. Na produkčních hostech se totiž častěji objeví binárka, která na první pohled nevypadá jako “klasický eskalační kandidát”: systemctl, jjs, vlastní helper nebo dokonce shell s omylem ponechaným SUID bitem.

Právě proto dává smysl uvažovat o SUID systematicky. Důležitá není popularita binárky, ale její chování:

Jarvis, Mango a Rope ukazují tři různé varianty stejného principu. Jedna binárka spravuje systemd, druhá interpretuje JavaScript s přístupem k Java API a třetí je obyčejný shell. Všechny ale při SUID bitu překračují hranici mezi běžným uživatelem a rootem.

Proč seznam SUID binárek sám nestačí

Výpis jako:

find / -perm -4000 -type f 2>/dev/null

je jen začátek. Samotný seznam neřekne:

GTFOBins je dobrý index, ale není to rozhodovací model. Jakmile se na hostu objeví méně běžný nástroj nebo distribuční specifikum, je potřeba přemýšlet nad tím, co ta binárka dělá, ne jen jestli už na ni někdo sepsal hotový one-liner.

Jak přemýšlet nad netypickou SUID binárkou

1. Umí spustit jiný proces

To je nejpřímější cesta k eskalaci. Nemusí jít o explicitní execve(). Stačí, že nástroj umí:

systemctl na Jarvisu je přesně ten případ. Není to shell, ale umí vytvořit a spustit systemd jednotku s libovolným ExecStart.

2. Umí číst nebo zapisovat libovolné cesty

Ne každá eskalace potřebuje shell. Pokud binárka s efektivním UID root umí otevřít libovolný soubor, už sama o sobě může stačit ke kompromitaci:

jjs na Mangu je dobrý příklad. Neotevíral rovnou root shell, ale umožnil přes Java API číst /root/root.txt. V praxi je to plnohodnotný root-read primitivum.

3. Je to interpreter, runtime nebo shell

Jakmile je SUID nastavený na obecném interpretru nebo shellu, bývá situace téměř vždy fatální. Shell, který zachová efektivní UID, nepotřebuje žádnou kreativní post-exploitation logiku. Prostě běží s root právy.

Rope je ukázkový extrém. Po technicky náročné user části stačilo najít /bin/bash se SUID bitem a spustit:

/bin/bash -p

Taková chyba je obranně katastrofální právě proto, že ruší smysl celé předchozí hardening vrstvy.

4. Umí pracovat s konfigurací, pluginem nebo jednotkou

Mnoho administrativních nástrojů není nebezpečných kvůli jednomu argumentu, ale kvůli tomu, že zpracovávají uživatelsky dodanou konfiguraci. To je opět Jarvis:

To je obecně silná heuristika. Pokud SUID binárka zpracovává externí jednotku, skript, šablonu nebo manifest, je potřeba ji auditovat jako cestu ke spuštění kódu.

Jak to vypadalo v konkrétních případech

Jarvis: SUID systemctl a vlastní systemd jednotka

Na Jarvisu ukázal linpeas mezi SUID binárkami systemctl. To samo o sobě už je varovný signál, protože systemd je centrální orchestrátor služeb. Praktický dopad byl přímočarý: stačilo vytvořit dočasný .service soubor s vlastním ExecStart, přilinkovat ho a nechat systemctl službu spustit.

Tady je důležité pochopit, proč je to nebezpečné. systemctl není problém jen proto, že “někdo našel trik”. Je nebezpečné z definice, protože umí delegovat spouštění procesu do systemd s root kontextem.

Mango: SUID jjs a file-read přes Java API

Na Mangu byl root mnohem méně nápadný. Mezi SUID soubory se objevil jjs, JavaScript shell pro Nashorn. Kdo čeká jen shellové utility, mohl by ho snadno přeskočit. Jenže jjs je interpreter s přímým přístupem k Java třídám. To znamená, že SUID jjs může:

echo 'var BufferedReader = Java.type("java.io.BufferedReader");
var FileReader = Java.type("java.io.FileReader");
var br = new BufferedReader(new FileReader("/root/root.txt"));
while ((line = br.readLine()) != null) { print(line); }' | jjs

To je přesně důvod, proč se SUID audit nesmí omezit na známé binárky z cheat sheetu. Interpreter s bohatým standardním API je často stejně silný jako shell.

Rope: SUID bash a zachování efektivního UID

Rope ukazuje nejjednodušší, ale zároveň nejdůležitější variantu: shell s omylem ponechaným SUID bitem. V takové situaci není co “exploitovat”. Stačí použít správný přepínač a shell si ponechá efektivní UID roota.

Technická náročnost předešlé části útoku zde není podstatná. Podstatné je, že jediný špatný permission bit na /bin/bash zrušil všechnu další obranu hostu.

Praktický postup po nalezení SUID binárky

1. Nejdřív priorizovat, ne zkoušet všechno

Po výpisu SUID souborů má smysl seřadit kandidáty podle chování:

Právě tahle priorizace bývá cennější než slepé opisování všech GTFOBins postupů.

2. Přečíst --help, man page a distribuční kontext

U netypické binárky je nejrychlejší zjistit:

systemctl, jjs i bash jsou odlišné nástroje, ale všechny už z dokumentace prozrazují schopnosti, které se se SUID bitem neslučují.

3. Nepřehlédnout read-only dopad

Někdy se po hledání root shellu snadno přehlédne, že binárka “jen” čte citlivé soubory. Obranně je to ale skoro stejný problém. Rootův SSH klíč nebo konfigurační tajemství mají často vyšší hodnotu než jednorázový interaktivní shell.

4. Vlastní binárky auditovat stejně přísně jako známé utility

Jakmile je SUID na interním helperu nebo méně známé utility, neznamená to menší riziko. Znamená to jen, že místo GTFOBins je potřeba krátká reverzní analýza nebo aspoň čtení dokumentace a argumentů.

Obrana a bezpečnější návrh

1. Pravidelně baselineovat SUID seznam

SUID soubory mají být malá, dobře odůvodněná množina. Jakmile se v ní objeví shell, interpreter nebo service manager, je to silný signál k okamžité revizi.

2. Nepoužívat SUID tam, kde stačí capabilities nebo úzké sudo

Pokud program potřebuje jen malý kousek privilegované funkce, je bezpečnější řešit to přes capabilities, socket activation nebo úzký wrapper než přes plný SUID root.

3. Odebrat SUID z obecných interpreterů a shellů

Shell, JavaScript runtime, Python nebo podobné nástroje nemají mít SUID bit. Jejich samotný účel je dostatečně obecný na to, že s efektivním UID roota z nich vzniká univerzální eskalační primitivum.

4. Auditovat distribucí dodané i lokálně přidané utility

Chyba nemusí být jen v custom helperu. Jarvis i Mango ukazují, že problém může vzniknout i na běžných součástech systému, pokud jim někdo omylem změní práva nebo způsob nasazení.

5. Sledovat neobvyklé používání SUID binárek

Spouštění systemctl, jjs nebo bash -p z nečekaného kontextu je silný detekční signál. Praktická obrana stojí nejen na odstranění SUID bitu, ale i na monitoringu toho, co se s podobnými binárkami děje.

Shrnutí klíčových poznatků

Co si odnést do praxe

tags: suid - gtfobins - linux - privesc - binaries