【ITニュース解説】XXE Injection in React.js — What It Is and How to Prevent It
2025年09月11日に「Dev.to」が公開したITニュース「XXE Injection in React.js — What It Is and How to Prevent It」について初心者にもわかりやすく解説しています。
ITニュース概要
Reactアプリで、ユーザーからのXML入力をAPIが安全でない形式で処理すると、「XXE Injection」の脆弱性が生じる。これにより、システム内の機密情報が漏洩したり、外部に攻撃されたりする危険がある。安全なXMLパーサーの採用や、外部エンティティの展開を無効化するなどのサーバー側での対策が不可欠だ。
ITニュース解説
システムエンジニアを目指す皆さんにとって、ソフトウェアの脆弱性は避けて通れない重要な知識である。特に、ウェブアプリケーション開発では様々なセキュリティリスクが存在し、その一つに「XXEインジェクション」というものがある。この記事では、このXXEインジェクションが何であるか、なぜ危険なのか、そしてReact.jsを使ったアプリケーションでどのように発生し、どうすれば防げるのかを初心者にも分かりやすく解説する。
XXEインジェクションとは、XML External Entity(XML外部エンティティ)の略で、XMLファイルを解析する際に発生するサーバー側の脆弱性のことである。具体的には、ユーザーがアップロードしたり、APIに送信したりするXMLデータに悪意のある記述が含まれていた場合、サーバー側のXMLパーサーがその記述を安全でない方法で処理することで、意図しない情報漏洩やシステムへの攻撃につながる可能性がある。React.jsのようなフロントエンドフレームワークを使うアプリケーションの場合、ユーザーがUIを通じてXMLデータを入力し、それがバックエンドのAPIに送信されてサーバーで解析されるという一連の流れの中で、この脆弱性が引き起こされることがある。
XXEインジェクションがどのようにして起こるのか、その仕組みを段階的に見ていこう。まず、Reactで構築されたユーザーインターフェース(UI)が、ユーザーからXML形式のデータを受け取る。これはファイルアップロードであったり、直接入力されたXMLテキストであったりする。次に、そのXMLデータはフロントエンドからバックエンドのAPIへと送信される。ここが問題の核心だが、バックエンドのXMLパーサーが、受け取ったXML内の「外部エンティティ」と呼ばれる特殊な記述を不用意に展開してしまうと、攻撃が成功してしまうのだ。外部エンティティとは、XMLファイル内で外部のファイルやURLを参照するための仕組みである。例えば、「file://」を使ってサーバー上のファイルを参照したり、「http://」を使って外部のWebサイトにアクセスしたりすることができる。もしパーサーが悪意のある外部エンティティを展開してしまった場合、サーバー上の機密ファイル(例えば、Linuxシステムでユーザー情報を含む/etc/passwdのようなファイル)の内容が攻撃者に読み取られたり、サーバーが外部の不正なWebサイトにリクエストを送信させられたりする「SSRF(サーバーサイドリクエストフォージェリ)」という攻撃につながったり、最悪の場合、パーサー自体がクラッシュしてサービスが停止したりすることもある。
具体的なXXEペイロード(攻撃コード)の例を見てみよう。以下のようなXMLデータがユーザーから送信されたとする。
<?xml version="1.0"?>
<!DOCTYPE data [
<!ENTITY xxe SYSTEM "file:///etc/hosts">
]>
<data>&xxe;</data>
このXMLには、<!DOCTYPE data [...]>という部分で「文書型定義(DTD)」が指定されている。このDTDの中で、<!ENTITY xxe SYSTEM "file:///etc/hosts">という記述がある。これは、「xxeという名前のエンティティを定義し、その内容はfile:///etc/hostsという外部ファイルから取得する」という意味になる。そして、<data>&xxe;</data>の部分で、定義したxxeエンティティを参照している。もしサーバーのXMLパーサーがこの外部エンティティの展開を許可していれば、パーサーはfile:///etc/hostsの内容を読み込み、それを&xxe;の部分に挿入してしまう。その結果、攻撃者はサーバーのhostsファイルの内容を入手できてしまうのだ。
フロントエンドであるReact側での対策は、あくまで補助的なものだと理解しておくことが重要だ。例えば、ファイルアップロード機能でXMLファイルのみを受け付けるようにチェックしたり、<!DOCTYPEという文字列が含まれるXMLをクライアント側で早期に拒否したりすることは、ユーザー体験の向上や簡単な不正な入力を防ぐのに役立つ。記事に示されているReactのコード例では、ファイルのMIMEタイプがtext/xmlまたはapplication/xmlであるかをチェックし、さらにファイルの内容に<!DOCTYPEが含まれていないかを検証している。これは良い習慣だが、クライアントサイドでのチェックは、簡単に回避できてしまうため、セキュリティの最終的な保証にはならない。本当のセキュリティ対策は、サーバー側で確実に行う必要があることを覚えておこう。
サーバーサイド、特にNode.jsのような環境でXMLを解析する際に、どのような設定が危険で、どうすれば安全になるのかを具体的に見ていく。
危険なパターンとして、libxmljs2のようなXMLパーサーを使う際に、誤ったオプションを設定してしまうケースがある。記事の例では、libxml.parseXml(req.body, { noent: true, dtdload: true, nonet: false });というコードが示されている。
noent: true:これはエンティティ(特に外部エンティティ)の展開を許可するという設定である。これが有効になっていると、前述の攻撃ペイロードのような外部ファイルの読み込みが実行されてしまう。
dtdload: true:これはDTDのロードを許可する設定である。DTDは外部エンティティの定義を含むことができるため、これを許可することはXXEインジェクションのリスクを高める。
nonet: false:これはXMLパーサーがネットワークアクセスを行うことを許可するという設定である。これが許可されていると、攻撃者がhttp://スキームを使った外部エンティティで、サーバーに任意のURLへのリクエストを送信させることが可能になる(SSRF攻撃)。
これらの設定が一つでもtrueになっていると、XXEインジェクションに対して脆弱な状態になってしまうため、絶対に避けるべきである。
では、どのようにすれば安全にXMLを解析できるのだろうか。安全なNode.jsのパターンでは、これらの危険なオプションを無効にする。記事の例では、以下の設定が推奨されている。
libxml.parseXml(req.body, { noent: false, dtdload: false, dtdvalid: false, nonet: true, noblanks: true, recover: true });
ここで注目すべきは、
noent: false:エンティティの展開を無効にする。これにより、外部ファイルの読み込みなどを防ぐ。
dtdload: false:DTDのロードを無効にする。これにより、悪意のあるDTDによる外部エンティティ定義を防ぐ。
dtdvalid: false:DTDの検証も無効にする。
nonet: true:ネットワークアクセスを無効にする。これにより、パーサーが外部のネットワークリソースにアクセスするのを完全に阻止する。
これらの設定を適切に行うことで、XXEインジェクションの主要な攻撃経路を遮断することができる。さらに、サーバー側でも受信したXMLボディに<!DOCTYPEが含まれていないかをチェックし、もし含まれていればリクエストを拒否するような多層防御の仕組みを導入することも非常に効果的である。これは、クライアント側でのチェックが突破された場合の最後の砦となる。また、express.text({ type: "application/xml", limit: "200kb" })のように、Content-Typeを厳格に指定し、かつ受信するXMLのサイズに上限を設けることも、DoS攻撃(サービス拒否攻撃)対策として重要である。
別の安全な方法として、最初からDTDや外部エンティティの解決をサポートしないXMLパーサーを選択するというアプローチもある。例えば、fast-xml-parserのようなライブラリは、設計上外部エンティティの展開を行わないため、XXEインジェクションのリスクを根本から排除できる。このようなパーサーを使用すれば、設定ミスによる脆弱性の発生を心配する必要が少なくなる。
最後に、アプリケーション全体のセキュリティパイプラインを強化するためのチェックリストを紹介する。
まず、サーバー側でDOCTYPEの宣言と外部エンティティの展開を必ずブロックすること。これがXXE対策の最も基本的なポイントである。
次に、DTDやXXEの機能をサポートしないXMLパーサーを優先的に使用することを検討しよう。これは予防的な対策として非常に有効である。
さらに、APIで受け取るXMLのContent-Typeを厳格にチェックし、サイズ制限を設けることで、不正なデータや過大なデータによる攻撃を防ぐ。
アプリケーションが稼働する環境自体もセキュリティ対策を施すべきだ。APIサーバーをネットワークが制限された環境、特に外部へのアクセス(エグレス)がデフォルトで無効になっているような環境で実行することで、たとえXXEインジェクションが成功したとしても、外部へのデータ送信や攻撃の拡大を防ぐことができる。
そして、開発プロセスにセキュリティテストを組み込むことも忘れてはならない。SAST(静的アプリケーションセキュリティテスト)やDAST(動的アプリケーションセキュリティテスト)をCI/CD(継続的インテグレーション/継続的デリバリー)パイプラインに含め、定期的にXXEインジェクションのテストを行うことで、脆弱性が見つかる前に修正し、安全なアプリケーションを維持することが可能になる。
システムエンジニアを目指す皆さんにとって、XXEインジェクションのような具体的な脆弱性とその対策を理解することは、セキュアなシステムを設計・開発するための基礎となる。フロントエンドとバックエンドが連携する現代のウェブアプリケーションにおいて、セキュリティは一方だけの問題ではない。それぞれの層で適切な対策を講じ、全体として強固な防御を築くことが求められる。この記事で解説した内容を参考に、安全なアプリケーション開発のスキルを習得してほしい。