【XXE編】XMLに混ざる悪意の参照とファイル漏洩の経路|CTF思考フレームワーク #17
こんにちは、アンペンです!
前回は、OSコマンドに混ざる悪意でRCEに至るコマンドインジェクションを扱いました。
今回は、XMLというデータ形式に潜むXXE(XML External Entity)を見ていきます。「データを送るだけ」のはずのXMLが、サーバ内部のファイルを読ませる入口に化ける仕組みを学びましょう。

XMLって、ただのデータ形式でしょ?それでファイル漏洩って、なんで?

XMLには『外部の値を読み込んで埋め込む』機能があるんだ。これが有効なまま入力を解析すると、サーバ内のファイルや内部URLを参照させられる。
XMLって、設定ファイルやデータのやりとりでよく見かける、おとなしい“データ形式”の代表ですよね。それがファイル漏洩の入口になると聞くと、ちょっと意外かもしれません。実はXMLには、見た目以上に“多機能”な一面があって、その親切機能のひとつが悪用されるのがXXEです。今日は、配達伝票に貼る“参照してね”の付箋にたとえて、その仕組みをほどいていきます。
XXEは、XMLパーサで外部実体参照(External Entity)が有効なまま信頼できないXMLを解析すると発生し、ローカルファイル読み取り・SSRF・DoSに至ります。守り方の基本は「外部実体参照を無効化」「DTD処理をオフ」です。
この記事で分かること
- XMLの「外部実体参照」が何をしているのか
- XXEで起きる3つの代表的な被害(ファイル漏洩・SSRF・DoS)
- パーサ設定で外部参照を無効にする守り方
📖 はじめてのWebセキュリティ #17|XXE編
『ただのデータ形式』に見えるXMLが、内部参照機能でファイル漏洩の入口になる仕組みを学びます。 シリーズ一覧を見る →
⚠️ 大事なお約束
この記事の確認は、CTF・公式ラボ・自分で作った検証環境だけで行ってください。実在するサービスにXXEペイロードを送る行為は、不正アクセスに該当する可能性があります。
XMLは『データ + 参照機能』を持っている
XMLはただのデータ形式ではなく、文書の冒頭(DTD)で「実体(エンティティ)」という変数のような仕組みを定義できます。さらに、その実体は「外部のファイルやURLを参照する」こともできます。
この機能が有効なパーサが、攻撃者が用意したXMLを処理すると、サーバ内部のファイルを読みに行って結果を埋め込むといった動きが起こります。
怖いのは、パーサ(XMLを読み解くプログラム)が、この“参照先”をなんの疑いもなく取りに行ってしまう点です。本文に &xxe; と書いてあれば、パーサは律儀に「じゃあ参照先のファイルを読んで、ここに貼り付けよう」と動く。攻撃者がその参照先を /etc/passwd のような内部ファイルに指定しておけば、サーバが自分から秘密を読み出して、応答に乗せて返してしまう——というわけです。
ポイントは、XMLが“ただのデータ”にとどまらないことです。XMLには、文書の先頭で『実体(エンティティ)』という、いわば“ショートカット”を定義できる機能があります。たとえば「&company; と書いたら『株式会社〇〇』に置き換える」といった具合。ここまでは便利な略語機能です。ところが、この置き換え先を“外部のファイルやURL”にもできてしまう——ここが、XXEの落とし穴の入口なんです。
図解:通常のXMLと外部実体参照入りXML

同じパーサに通しても、文書の中身次第で「ただの値」を返すか、「内部ファイル」を返すかが変わります。

配達伝票の備考欄に「ここの内容は、別の倉庫の資料を見て埋めてください」と付箋で指示できる仕組みがあるとします。本来は社外向けの資料を指し示すための機能でも、悪用されれば「金庫の中身を貼り付けてください」のような指示が混ぜられかねません。XMLの外部実体参照も、まさにこの『参照する力』が悪用される構造です。
ここで覚える用語:外部実体参照(External Entity)
XMLのDTDで定義できる仕組みで、 <!ENTITY xxe SYSTEM "file:///etc/passwd"> のように外部リソースを参照する実体を作れます。これがパーサ側で有効になっていると、XML本文中で &xxe; と書くだけで内部ファイルの中身に置き換わってしまいます。
整理すると、攻撃の流れはこうです。①攻撃者がXMLの先頭で「xxe という実体は、/etc/passwd を指す」と宣言する。②本文で &xxe; と書く。③パーサがそれを“ファイルの中身”に置き換える。④結果が画面やエラーに表示される。たった数行のXMLで、サーバの中身がのぞけてしまうわけです。しかも使うのはXMLの“正規機能”なので、文法エラーにもならず、すんなり通ってしまうのが厄介なところです。
XXEで起きる代表的な3つの被害
XXEの被害は、大きく3つに広がります。『内部ファイルを読み取る』『内部のURLを叩く(#11で見たSSRFと同じ)』『わざと爆発的に展開させてサーバを止める(DoS)』。とくに2つ目は、XXEがSSRFの“発射台”にもなることを意味します。一つの入口から、複数の攻撃が枝分かれしていくんです。
よくある被害パターン

- ローカルファイル読み取り:
file:///スキームで/etc/passwdや設定ファイルを読み出す - 内部SSRF:
http://スキームで内部APIや管理画面を叩く(SSRFと同じ被害) - DoS(billion laughs):実体を多段ネストさせ、展開で爆発的にメモリを消費させる
XML処理は古くからある分、設定が緩いまま残っているライブラリも多く、画像メタデータ・SVG・SAML・SOAPなどXML周辺の至るところに混入経路があります。
ここで知っておきたいのが、『XXEは“古い親切”の置き土産』だということ。XMLは歴史が長く、外部参照は昔は便利機能として標準で有効になっていました。その名残で、いまも古いライブラリでは初期設定のまま危険、というケースが残っています。しかも厄介なのは、自分では“XMLなんて使っていない”つもりでも、SVG画像、Officeファイル、SAMLログイン、SOAP通信など、裏でXMLを処理している場所が意外と多いこと。「どこでXMLを読んでいるか」の棚卸しが、最初の一歩になります。
練習は、自分のコードやライブラリで“XMLを読んでいる場所”を探し、その設定を確かめることです。攻撃ペイロードを本物に送る必要はありません。「このパーサ、外部参照を切ってあるかな?」と一つずつ確認するだけ。地味ですが、XXEはこの確認だけで大半を未然に防げる、コスパのいい対策なんです。
CTFでやってみよう:XMLパーサ設定を観察する
自分の検証環境のコードで、XMLパーサの設定を確認しよう
目的は本物のサービスを攻撃することではなく、「外部実体参照が有効になっていないか」を見ることです。
- CTFや自分のラボのコードで、XMLパーサ(lxml, xml.etree, libxml, JAXP等)の利用箇所を検索する
- パーサ初期化で「外部参照無効化(no_entity, disallow_doctype)」などの設定がされているかを確認
- SVGや画像メタ、SOAP/SAMLライブラリなど、XMLを内部で扱う依存パッケージを洗い出す
- 独自定義の実体参照が含まれた小さなテストXMLをパースし、解決結果を見る(ラボ限定)
- JSONに置き換えられる経路がないか合わせて検討する
file:/// を含むXMLを送る試行は絶対にやめてください。確認は自分のラボ・自分のコードの範囲だけです。守りについては、うれしいお知らせがあります。XXEは“設定一発”で大半が消える、数少ない脆弱性なんです。

外部参照を切っちゃって、普通の機能まで動かなくならない?

そこは安心していいよ。外部の実体参照(ファイルやURLを取りに行く機能)なんて、ふつうのアプリではまず使わないんだ。だから切っても、日常のXML処理はまったく困らない。むしろ“便利だけど誰も使っていない危険機能”を、最初からオフにしておくイメージ。各言語に『安全な初期設定』のお手本があるから、それに従うだけで一気に堅くなるよ。
守る側なら、「外部実体参照を無効化」がほぼ全て
XXEの守りは、「外部実体参照・DTD処理をデフォルトで無効化する」のひと言に尽きます。設定一つで防げる種類の脆弱性なので、まず棚卸しから始めるのが効果的です。
- XMLパーサで外部実体参照とDTDをデフォルトで無効化する(言語ごとの推奨設定に従う)
- 古いパーサ・ライブラリは安全なバージョンに更新する
- SVG・画像メタ・SAML・SOAPなど、XMLを内部で扱う処理を一覧化し、同様の設定を適用する
- 可能ならXMLからJSONなど別形式に移行する
- XML受け取り口にスキーマ検証を入れ、想定外の構造を弾く
- WAFで
!DOCTYPEやSYSTEM "file:"を含む要求をブロック・検知する

『参照しないパーサ設定』ってまずすべきことなんだね。

そう。XXEは設定で大半が消える種類の問題だから、ライブラリ棚卸し+共通設定が一番効くよ。
ここまでをひと言で言うと、XXEは『XMLパーサに“外を見るな”と命じておく』だけで、ほぼ封じられます。多くの攻撃が設計や習慣の積み重ねで守るのに対し、XXEは“設定スイッチ一つ”が効く珍しいタイプ。だからこそ、後回しにせず、XMLを読むすべての場所に同じ設定を行き渡らせることが大切です。
まとめ:XMLパーサは『参照しない』が標準
- XMLは『データ + 参照機能(DTD/Entity)』を持つ
- 外部実体参照が有効だとファイル漏洩・SSRF・DoSが成立する
- 守りは外部実体参照・DTD処理を無効化するパーサ設定が中心
- SVGやSAMLなど、XMLを内部で使うライブラリも忘れずに棚卸し
今日の持ち帰りは『XMLは便利すぎる、だから“参照”は切っておく』です。おとなしく見えるデータ形式の裏に、ファイルを読みに行く力が眠っている——そう知っておくだけで、見方が変わります。外部実体参照とDTDを無効化する。たったこれだけで、ファイル漏洩もSSRFもDoSも、まとめて入口を塞げます。
次回は、複数の中継装置(プロキシやLB)で解釈がズレることを突くHTTPリクエストスマグリングを扱います。境界の解釈ズレを突く攻撃を見ていきましょう。
