XPathインジェクション:XMLの「裏口」を塞ぐための最前線知識
「XML? まだそんなレガシーな技術を使っているのか?」と鼻で笑うエンジニアもいるかもしれない。だが、金融、物流、そして企業のレガシーな基幹システムにおいて、XMLは今もなお血脈として流れ続けている。そして、XPathインジェクションは、SQLインジェクションほど話題にならない分、攻撃者にとっては「誰も見張っていない裏口」になりやすい非常に厄介な脆弱性だ。
今日は、教科書的な説明は抜きにして、現場の泥臭い知見と「どう書けば絶対に抜かれないか」という一点に絞って解説する。
—
1. XPathインジェクションのメカニズム:なぜ「クエリ」は裏切るのか
XPathインジェクションの本質は、SQLインジェクションと全く同じだ。「ユーザーからの入力を、命令(クエリ)の一部として結合してしまうこと」にある。
例えば、ユーザー名でXML内のユーザー情報を検索する処理を考えてみよう。
// 脆弱な実装例:最悪のコード
$username = $_POST[‘username’];
// クエリを文字列結合で組み立てる
$query = “//user[name/text()='” . $username . “‘]”;
$result = $xml->xpath($query);
もし、攻撃者が username に ' or '1'='1 を入力したらどうなるか? クエリはこう変化する。
//user[name/text()='' or '1'='1']
結果、条件式は常に真となり、XML内の全ユーザー情報がごっそりと引き抜かれる。これがXPathインジェクションの初歩的なPoCだ。さらに恐ろしいのは、count() 関数などを使ってブラインドインジェクションを仕掛けられ、1文字ずつXMLの構造を暴かれるケースだ。これはもはや、情報漏洩のフルコースと言える。
—
2. 鋼鉄の防御:パラメータ化という唯一の正解
現場で最もやってはいけないのが「入力値のサニタイズ(エスケープ)」に頼ることだ。addslashes() や独自のエスケープ関数で凌ごうとするのは、イタチごっこの始まりに過ぎない。
唯一の正解は「XPath変数の利用」だ。 SQLにおけるプリペアドステートメントと同じ概念をXMLでも適用する。PHPの DOMXPath::registerNamespace や、各言語が提供する変数バインド機能を強制的に使わせるのが、チームリーダーとしての鉄則だ。
実践:PHPにおけるセキュアな実装コード
以下のコードは、PHPでXPath変数を正しく利用する例だ。これなら、いかなる悪意ある入力値も「データ」としてのみ扱われる。
// セキュアな実装:DOMXPath::registerNamespace と変数の活用
$dom = new DOMDocument();
$dom->load(‘users.xml’);
$xpath = new DOMXPath($dom);
// 検索したい値を「変数」として用意する
$userInput = $_POST[‘username’];
// クエリには変数を埋め込む(XPathの変数指定は $ を使用)
// ※事前に registerNamespace などで環境を整えておくことが前提
$query = “//user[name/text()=\$target]”;
// 変数をバインドする
$xpath->registerVariable(‘target’, $userInput);
// 実行(これでインジェクションは物理的に不可能になる)
$result = $xpath->query($query);
—
3. インフラ・レイヤーでの防御:多層防御の考え方
開発者がミスを犯すことを前提に、インフラ側でもう一段の壁を築く。もし君がインフラ担当なら、WAFの設定を見直してほしい。
WAF (AWS WAF / ModSecurity) の対策ポリシー
WAFでXPath関連の演算子やメタ文字を完全に排除するのは難しいが、異常なクエリパターンを検知することは可能だ。
- 検知すべきシグネチャの例:
//: 全ノードへのアクセスを試みるパターンcount(/): ブラインド攻撃の兆候name(),local-name(): 構造を探索する関数の利用
Nginx等の設定で防ぐべき点:
もし外部にXMLを直接公開しているなら、XMLパース時の「XXE(XML外部エンティティ攻撃)」もセットで防ぐ必要がある。libxmlのオプションで外部エンティティを無効化する設定(libxml_disable_entity_loader(true))を、コードの冒頭に必ず入れておくこと。
—
4. チーフエンジニアからの提言:コードレビューで見るべきポイント
最後に、チームのコードをレビューする際、君がチェックすべきは以下の2点だけだ。
1. 文字列連結の有無: " や . を使ってXPathのクエリ文字列を組み立てていないか? 一箇所でも見つけたら、それは即座に修正対象だ。
2. XMLの用途: そのXML操作は本当に必要か? JSONへの移行が可能なら、今すぐ技術的負債を解消すべきだ。XMLは複雑怪奇で、セキュリティの穴が生まれやすい。
インシデントは「まさか」という場所で起きる。しかし、我々エンジニアにとって「まさか」は「想定外」であってはならない。今日解説したXPathインジェクションの対策は、セキュリティの基本中の基本だ。明日からの開発で、文字列連結によるクエリ生成をチームから根絶してほしい。
技術は常に進化するが、攻撃者の狙いはいつだって「楽な入り口」だ。君たちがその入り口を一つずつ塞いでいくことで、システムは真に堅牢なものになる。健闘を祈る。
コメント