【テクニカル・上級編】XPathインジェクション:XMLデータベースに対するクエリ操作 – アプリケーションセキュリティ & 安全な開発防御ガイド

XPathインジェクションの深淵:XML構造をハックする「盲点」を突く

多くのエンジニアは、SQLインジェクションには過敏なほど反応する。しかし、システムがXMLデータベースや設定ファイル、あるいはSOAPベースのレガシーなAPIを扱う際、XPathに対して同様の警戒心を持っているかといえば、答えはNOだ。

XPathインジェクションは、単なる「クエリの改竄」ではない。それはXMLの木構造(Tree Structure)を操作し、本来到達不可能なノードへアクセスし、さらには外部エンティティ参照(XXE)と組み合わせることで、OSの深部まで侵食するトリガーになり得る。

今日は、教科書的な「サニタイズしましょう」という甘い言葉は捨てて、アーキテクトが直面すべき「XMLパーサの深層」と「防御のアーキテクチャ」について掘り下げたい。

—

1. なぜXPathインジェクションは「盲点」なのか

SQLiがデータベースのテーブル構造をターゲットにするのに対し、XPathは階層構造(DOM)そのものを標的とする。攻撃者は、' or '1'='1のような初歩的なクエリで、XML内の全ノードを列挙し、認証バイパスや機密情報の抽出を試みる。

問題の根源は、XPathエンジンが「データ」と「制御構文(パス式)」を厳密に分離していないことにある。特に、動的に構築されるXPath文字列は、パーサにとって「どこまでが検索対象で、どこからがロジックか」という境界が極めて曖昧だ。

例えば、ユーザー入力をそのままクエリに連結している場合、攻撃者は' | //user/password | //といったパス式を注入し、ノードのOR演算によって、本来見るべきではないpasswordノードを抽出する。これは、SQLのUNION SELECTと同等の破壊力を持つ。

—

2. 防御のアーキテクチャ:コンパイル済みXPathの強制

個別の入力値をチマチマとエスケープ(サニタイズ)するのは、現代のセキュリティアーキテクチャとしてはナンセンスだ。ブラックリスト方式のフィルタリングは、常に攻撃者の創造性に敗北する。

我々が採用すべきは、「パラメータ化されたXPath式」の利用である。SQLにおけるプリペアドステートメントと同様の概念を、XPathコンテキストでも適用する。

実装サンプル:Java (javax.xml.xpath) による安全な実装

// 不適切な実装: 文字列連結でクエリを構築してはいけない
// String xpath = “//user[username='” + inputName + “‘]”;

// 推奨される実装: XPathVariableResolver を使用したパラメータ化
public Object evaluateXPath(String inputName, Document doc) throws Exception {
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();

// 変数リゾルバを定義し、入力を式から分離する
xpath.setXPathVariableResolver(variableName -> {
if (variableName.getLocalPart().equals(“username”)) {
return inputName; // 入力値は純粋なデータとして扱われる
}
return null;
});

// $username という変数を介して値をバインドする
XPathExpression expr = xpath.compile(“//user[username=$username]”);
return expr.evaluate(doc, XPathConstants.NODESET);
}

このアプローチの肝は、入力値がXPathの「式」として評価される可能性を完全に排除している点にある。メモリ上のXPath抽象構文木(AST)を構築する段階で、入力値はただの「リテラル値」として埋め込まれるため、どれほど悪意のあるパス式を注入されても、パーサはそれを単なる文字列としてしか認識しない。

—

3. 生成AI時代の「ガードレイル」設計

昨今のLLM(大規模言語モデル)をインターフェースに利用するシステムでは、プロンプトインジェクションを通じてバックエンドのXPathが攻撃されるリスクが急増している。

アーキテクトとして、以下の「多層防御(Defense in Depth)」を推奨する。

1. 入力の正規化と型制約: XPathの入力値に対して、厳格なスキーマ検証(XML Schema / XSD)を適用せよ。
2. パーサの制限: 使用するXMLパーサにおいて、外部エンティティの解決(XXE)や、DTD(文書型定義)の読み込みを明示的に無効化する。これはXPathインジェクションの被害範囲を限定するための必須設定だ。
3. サンドボックス化: XMLデータベースを扱うプロセスには、最小権限の原則(Principle of Least Privilege)を適用し、ファイルシステムへの書き込み権限やネットワーク通信権限を剥奪する。

—

4. 最後に:セキュリティは「構造」に宿る

XPathインジェクションを防ぐために最も重要なのは、コードの修正以上に、「ユーザー入力を信頼しない」というアーキテクチャ上の規律だ。

インシデント対応の現場でよく目にするのは、単なるバリデーション漏れではなく、「なぜそのXMLにアクセスする必要があるのか」「なぜそのクエリが動的に生成される必要があるのか」という設計思想の欠落である。

攻撃者は、あなたのシステムが「XMLをどうパースし、どうメモリにロードしているか」という低レイヤの挙動を、執拗にスキャンしている。我々エンジニアは、パッチを当てることではなく、脆弱性が入り込む余地のない強固なデータ構造を設計することにこそ、真の知性を費やすべきだ。

セキュリティとは、技術の積み重ねであると同時に、攻撃者の思考に対する「先回り」である。コードを書くとき、ふと立ち止まって考えてほしい。そのクエリは、誰かの悪意を「命令」として受け取っていないだろうか。

コメント

タイトルとURLをコピーしました