XML外部実体参照(XXE)は、XMLパーサの正当な機能を悪用して、ファイル読み取りや内部アクセスを引き起こす脆弱性です。 対策は明快で、パーサの外部実体とDTDの処理を無効化できているかどうかで決まります。
XML外部実体参照とは
XML外部実体参照(XXE):XMLの外部実体(external entity)を解決する機能をパーサが有効にしていると、攻撃者が定義した実体を通じてサーバ上のファイルや外部リソースを読み込ませられる脆弱性です。 XMLを受け取って解析する箇所で、外部実体の解決が既定で有効になっていることが根本原因になります。
攻撃者は <!ENTITY xxe SYSTEM "file:///etc/passwd"> のような定義でサーバ内のファイルを読み取ります。
さらに実体の参照先を内部URLに向ければSSRF、多重に展開される実体を使えばメモリを枯渇させるDoS(billion laughs攻撃)に至ります。
XMLを受け取る箇所は自覚されにくく、APIの一機能やファイル解析の内部でひっそり動いていることが多いのも、見落とされやすい理由です。
XML外部実体参照が起きるパターン
典型的な混入箇所は次のとおりです。
- 外部からのXMLを、外部実体とDTD処理を無効化していない既定設定のパーサで解析している
- SOAPやXMLベースのAPI、RSSやSAMLなど、XMLを受け取るエンドポイント
- SVG画像やdocx、xlsxなどのOfficeファイルの中身がXMLであり、アップロードされたファイルの解析経由で間接的に成立する
- ライブラリの古いバージョンで、外部実体解決が既定で有効になっている
共通するのは「外部から受け取ったXMLを、外部実体を解決できる状態のパーサで処理している」という点です。
対策法
原則は「XMLパーサの外部実体解決とDTD処理を無効化する」ことです。
- 使用するパーサで外部実体(external general/parameter entity)とDTDの読み込みを無効化する。これが本命の対策になる
- そもそもDTDを許可しない設定(
disallow-doctype-declなど)を選べるなら、それを使う - XMLが必須でないインターフェースは、JSONなど実体解決の概念がない形式に置き換える
- SVGやOfficeファイルのアップロードでは、中身のXMLも同じ方針で安全に解析する
- パーサやライブラリを、外部実体が既定で無効な新しいバージョンに保つ
入力のフィルタリングでDOCTYPE宣言を弾く方法は回避されやすく、本命はパーサ設定での無効化です。 まずXMLを受け取る全経路を洗い出し、共通の安全な解析設定に寄せるのが費用対効果の高い進め方になります。
Rails での事例
Rails で XML を解析する定番は Nokogiri です。
デフォルトの Nokogiri::XML() は外部実体を解決しない安全側の設定ですが、NOENT オプションを付けると実体を展開するようになり、これが XXE の入り口になります。
# 危険:NOENT は「実体参照を展開する」オプション。名前に反して有害
doc = Nokogiri::XML(params[:xml]) do |config|
config.noent
end
Nokogiri::XML::ParseOptions::NOENT は「no entity(実体なし)」ではなく「実体を展開せよ」の意味で、名前から受ける印象と逆に働きます。
このオプションを付けないのが基本です。
デフォルトの Nokogiri::XML は、実体を展開せず、外部DTDの読み込みもネットワークアクセス(NONET)も行いません。
つまり素直に解析するかぎり安全側に倒れます。
# 安全:デフォルトのまま。実体は展開されず、外部リソースも取得しない
doc = Nokogiri::XML(params[:xml])
やるべきことは、この安全な既定を自分で外さないことです。
dtdload(DTD の読み込み)や noent(実体の展開)を有効化するオプションを付けていないか、Nokogiri::XML の呼び出し箇所を検索して確認します。
見落とされやすいのは、XML を直接受け取っていないつもりの経路です。 SVG 画像や docx、xlsx の中身は XML であり、アップロードされたこれらのファイルを解析するライブラリが内部で XML パーサを呼びます。 ファイルアップロードを受け付ける機能でも、解析ライブラリが外部実体を無効化しているかを確認します。 XML が必須でないインターフェースなら、JSON へ置き換えることで問題の経路自体をなくせます。
まとめ
XML外部実体参照(XXE)対策の要点を整理します。
- 根本原因は「外部から受け取ったXMLを、外部実体を解決できる状態のパーサで処理していること」。対策の本命はパーサ設定での無効化で、入力のフィルタリングは本命にならない
- Nokogiri はデフォルトが安全側。
noent(名前に反して「実体を展開せよ」の意味)やdtdloadを自分で有効化しないことが基本になる - SOAP・SAML・RSSなどXMLを受け取るAPIだけでなく、SVGやdocx・xlsxといった「中身がXML」のファイル解析経由でも成立する
- 被害はファイル読み取りにとどまらず、参照先を内部URLに向けたSSRF、実体の多重展開によるDoS(billion laughs攻撃)にも広がる
- XMLが必須でないインターフェースは、JSONへの置き換えで問題の経路そのものをなくせる
点検は「XMLを受け取る・解析する経路の棚卸し」から始まります。API のエンドポイントだけでなく、ファイルアップロードの解析処理まで含めて洗い出し、パーサの設定を共通の安全な形に寄せるのが着実な進め方です。
関連して読める記事
XXEの被害の広がり方を理解するには、SSRF(サーバサイドリクエストフォージェリ)とセットで整理するのが近道です。外部実体の参照先を内部URLに向けるXXEは、XMLパーサを経由したSSRFそのものと言えます。「外部入力が構文として解釈される」というインジェクションの構図はSQLインジェクションと共通し、「サーバ内のファイルを読み取られる」という被害の面ではパストラバーサルと同じ結果に至ります。

SSRF(サーバサイドリクエストフォージェリ)とは?起きるパターンと対策法
SSRF(サーバサイドリクエストフォージェリ)の仕組みと起きるパターン、宛先ホストの許可リストとクラウドメタデータ保護(IMDSv2)を軸にした対策を整理します。Railsで URI.open にユーザー指定URLをそのまま渡してしまう危険例と、許可リスト+内部IP検証を組み込んだ安全な実装、DNSリバインディングまで含めた検証の勘所を具体的なコードで示します。
2026年7月24日
SQLインジェクションとは?起きるパターンと対策法
SQLインジェクションの仕組みと起きるパターン、そしてプレースホルダ(パラメータ化クエリ)を軸にした対策を整理します。Rails(Active Record)で穴が開く where の文字列展開と order のカラム名、その安全な書き方を具体的なコード例で示します。
2026年7月22日
パストラバーサルとは?起きるパターンと対策法
パストラバーサル(ディレクトリトラバーサル)の仕組みと起きるパターン、正規化後の範囲チェックと許可リストを軸にした対策を整理します。Railsで send_file にファイル名パラメータをそのまま渡してしまう危険例と、File.expand_path による正規化+前方一致の検証、入力を「パス」ではなく「ID」にする設計まで具体的なコードで示します。
2026年7月24日