Drive
Hack the Box machine writeup

Summary
Drive was a box on the easier side of the hard difficulty. It involves some pretty straightforward steps and a little bit of reversing. Many of the steps center around finding plain text creds and none of it is overly technical until Root. To obtain user.txt first the attacker will enumerate an IDOR vulnerability that will let them read other users' files on the web application. One of these files contains creds that can be used to login with SSH and obtain a foothold shell as Martin. Next a tunnel to port 3000 must be established to bypass port filtering and access a Gitea instance. The attacker can reuse Martins creds here to discover a repository that contains a backup.sh script and a hardcoded password. Going back to the drive.htb server the attacker can find a bunch of backup 7z archives that can be unzipped with the discovered password. These archives contain password hashes that can be cracked to obtain a shell with the Tom user over SSH.
The root step mainly involved the reversing of an ELF executable. In doing so an SQL injection is discovered that when combined with the run-time loadable extensions function of sqlite allows for arbitrary C code to be run. Abusing this then allows for escalation to root as the ELF executable is run with suid permissions.

User
Recon
Nmap scan
Starting off with an nmap scan reveals SSH open on port 22, an nginx web server redirecting to http://drive.htb on 80 and a filtered port 3000.
I will then add drive.htb to my /etc/hosts file for DNS resolution.
Fuzz for subdomains
Whenever I discover a domain I like to fuzz for other subdomains or virtual hosts that might exist. In this case there was nothing to be discovered
Enumerate Webserver
Navigating to drive.htb displays a generic company page for a web application called Doodle Grive. There are tabs for Home, About, Services, Team, and Contact Us. About, services and team are all simply anchored to points on the main page.
Contact us is a generic contact form.
Sending this through burp and looking at the server response headers does not reveal anything of value like a framework. It will also print a message about contacting us soon.
Home links to /home/ which appears to be the doodle gdrive web application. At this directory there is a file called Welcome_to_Doodle_Gdrive that links to a login form, /login. This form can also be reached by the login button found in the top right.
Guessing some basic stuff like admin:admin doesn't get anywhere and it does not appear like the error message will allow us to enumerate usernames. There is a register link at the bottom however and using this to register a new account we can then login.
Upon logging in we are redirected back to the home page. Clicking dashboard will bring us back to /home/ and we are now able to view the message in the Welcome file.
Going back and clicking upload we are directed to /upload. Here we can upload a file to the service that is the ASCII text mime type.
Uploading the file we are redirected to /home/ and can see the new file. Clicking on it we are given the new options of change properties, delete and edit content. delete and edit content do what you would think.
Change properties redirects to /112/update where the name of the file can be changed.
Reports generate a log of activity on the service.
Lastly there is groups that will allow the user to create groups and upload files to the group.

Fuzzing for IDOR
At this point it becomes clear that there is some kind of object referencing going on in the urls. For example we have: /112/update, /112/getFileDetail/ and /112/editContent. It is possible that we can change the 112 to reference another file and exploit an Indirect Object Reference through the URL. To test this we can use /getFileDetail as it will likely allow us to read other files. Testing with /0/getfiledetails simply returns a json internal server error that states no file matches the given query. At this point it is a good idea to attempt to fuzz the value. For this we will use Wfuzz and pass it the csrf token and session id cookies from an intercepted burp request in order to authenticate the Wfuzz requests.
I will also use the --hh 82 flag to filter out the default responses with chars length 82 like we did when fuzzing for subdomains.
This returns our known 112 test file but also 100 which is the Welcome_to_Doodle_Grive! file. The other values return a 401 unauthorized response, likely because these are owned by other users. Thinking that perhaps one of the functions that references the files: /block, /update or /edit Content might not correctly apply the authorization filtering I fuzzed those with the value 079 from the unauthorized above. /079/block/ returns a file titled announce_to_the_software_Enginner and with it we have found and confirmed an IDOR vulnerability that allows us to look at other peoples files we should not have access to.
Viewing this file, announce_to_the_software_Engineering_team, we can find credentials for a user martin with the password Xk4@KjyrYv8t194L!.

Using the same IDOR to view the other files 101 reveals a message about a scheduled database backup plan. it also gives us a couple more users of jamesMason and Cris.
098 just gives us a generic message and another user of crisDiesl. 99 just reveals a message about there being security issues in the middleware.
Shell as Martin
Using the creds we found martin:Xk4@KjyrYv8t194L! we can SSH into the drive.htb host.

As we do not yet have user.txt we can check the home directory and see that we likely will need to move laterally to the cris or tom users. We can also see a git user, signaling that the filtered port 3000 was likely a git hosting service.
Using netstat we can see the 3000 port listening on all addresses. we can also see there is a mysql server listening locally on port 3306 and likely port 33060.
Tunnel to access Gitea
Using curl to access the port 3000 server from the localhost we can see that the port filtering is bypassed and we are returned to the Gitea website. From here I used SSH to set up port forwarding for the 3000 port. In this way we can use the tunnel to access the website from our attacking hosts browser and bypass the filtering.

Using explore we cannot find any repositories and we are only shown user accounts we already know. We can try logging in with martins creds. While this does not work with username martin, it does let us in with martin@drive.htb. We can now see the DoodleGrive repository in explore.
In this repository there is the db_backup.sh script that was mentioned in one of the files on the web application we discovered. This script file contains the hardcoded password H@ckThisP@ssW0rDIfY0uC@n:) which is used to create the backup zip files. If we find these backups we can likely use this password to decrypt them.

Exploring backups
The note about the backup script also mentioned the /var/backups directory we can check it out. Here we can see a DoodleGdrive.zip folder owned by www-data that we cannot read, meaning we likely have to get a shell as www-data at some point.
Checking out /var/www there is a backups directory here as well. In /var/www/backups there are a bunch of .7z backups we can read this time as well as a db.sqlite3 file.
To quickly transfer all these back to my attacking machine I will abuse the python3 installed on drive.htb to create a simple http server on port 42069. I will then use wget with the recursive -r flag to pull all the files from the newly created web server directory.
I decided to check out the db.sqlite3 database first since it was unencrypted. Browsing this database it appears to be connected to the web application as we can find the files we had previously discovered in the myApp_file table.
In the accounts_customuser table we can find 5 password hashes for different user accounts. adding all these hashes to a file and using hashcat we can crack the password for the tomHands user to john316

Sadly this password does not work for SSH or anything else. From here it was time to use the previously discovered password to decrypt and unzip all the backup .7z archives.
These databases are much like the previous one already went through. We will do the same process as before , copying all the hashes to a text file and running that through hashcat. The database for December contains a different hash type that will take forever to crack, as such I will not add these ones to the list. This will result in 2 more passwords for the tom user and the one we already discovered.

Shell as Tom
Spraying these 2 new passwords against SSH we get in with johnmayer7. We can then grab user.txt and move on to exploiting root.

Root
Enumeration
In tom's home directory we can find a suid binary called doodleGrive-cli. we can see that the file is an ELF binary. Running it we are asked for a username and a password.
Finding password for binary
Finding the password and username for the binary was as easy as running as strings command, which will print out all the ascii strings, and then grepping for the password. Assuming the check is either right before or after the password prompt we can add the --before 5 and --after flag to print 5 line before and after the match.
We can see from this command that the user name is Moriarty and the password is findMeIfY0uC@nMr.Holmz!. Running the binary with these credentials results in an interactive application with a menu of 6 options. I played around with this a bit but without reversing the application it is hard to know what exactly is going on.

Reversing doodleGrive-cli
The first thing to do was to transfer the application back to my host machine. I will do this the same way as before using a python simple http server.
Next I opened the executable in Ghidra, disassembled and analyzed the file. Doing so we can see the main_menu function. This contains the 5 choices we saw before as a switch statement which each calls a separate function.
Looking at these functions we can see that they are all making SQL queries with sqlite3 and returning the data. In case 5 calling the activate_user_acount function we appear to have the first case of interactivity with the SQL and an apparent SQL injection as we are able to control input into the query. There is a santize_string that attempts to prevent us from doing this however which we can see directly before the SQL query.
Looking at the santize_string function we can see that it is doing some checks on the passed value.
Decoding the hex we can see that local_29 is a set of bad chars {/| '. we can also see that local_21 is a ;. We can assume that these are bad chars we will need to avoid while creating the SQL injection.

Creating SQLITE injection
Looking back at the SQL query we can see that sqlite3 is being used. This is good because it allows us to execute arbitrary code through a function called run-time loadable extensions. This effectively allows us to execute external .so scripts with the load_extension command. The ability to run code in this way though external scripts is not unique to sqlite3 and is also present in things such as Microsoft SQL server as an important note.
Therefore we can use an input such as "+load_extension(script to run)--" to inject arbitrary code into the SQL statement to be executed. In order to do this we will need a .so file however. We can create one now and upload it to the same directory as the doodleGrive-cli binary. By keeping it in the same directory location we can reference it simply as ./nameoffile.
This code will attach suid permissions to the /bin/bash binary, allowing anyone to run it with the -p flag to obtain root permissions. Next we need to compile it with GCC.
This will make our SQL injection look as follows, using + to avoid spaces as SQLite treats + as whitespace.
There is a problem though as the / character won't get past the sanitation. To get around this we can use the char sqlite3 function to pass in a series of char ascii digits instead. To make this even easier on ourselves we will rename hack.so to a.so so we require less chars. One final thing that helps us out is that when sqlite uses the load_exension function it automatically applies the .so at the end. Due to this we only need the char values of . / and a. We can use an online chart for this. Putting this all together you can see the final version of the injection string below with 46 being . 47 being / and 97 being a.

Use run-time loadable extensions
We now have everything setup and configured as needed to execute the SQL injection and abuse run-time loadable extensions to execute our a.so code and achieve root.
We can now check that the /bin/bash binary was given suid privileges and run it with the -p flag to read root.txt and complete the box.

Additional Resources
Last updated
