XPathインジェクション攻撃について
XPathインジェクション攻撃は、WebアプリケーションがXMLデータベースに対してユーザー入力に基づくXPathクエリを実行する際に発生する脆弱性です。攻撃者は、ユーザー入力に悪意のあるXPathクエリを含めることで、データベースから意図しない情報を取得したり、不正な操作を実行したりすることができます。XPathインジェクションは、SQLインジェクションに似た攻撃手法ですが、対象となるのはSQLデータベースではなく、XMLデータベースやXML文書です。
脆弱なコード:
<?php
$xml = simplexml_load_file('users.xml');
$username = $_GET['username'];
$password = $_GET['password'];
$query = "//user[username/text()='$username' and password/text()='$password']";
$result = $xml->xpath($query);
if (!empty($result)) {
echo "Login successful!";
} else {
echo "Invalid username or password.";
}
?>
攻撃手法:
攻撃者がusername
フィールドに' or '1'='1
を入力し、password
フィールドに' or '1'='1
を入力すると、次のようなXPathクエリが生成されます。
//user[username/text()='' or '1'='1' and password/text()='' or '1'='1']
このクエリは常にtrue
を返すため、どのユーザーに対しても認証が成功してしまいます。
脆弱なコード:
import xml.etree.ElementTree as ET
tree = ET.parse('users.xml')
root = tree.getroot()
username = input("Enter username: ")
password = input("Enter password: ")
query = f".//user[username='{username}' and password='{password}']"
result = root.findall(query)
if result:
print("Login successful!")
else:
print("Invalid username or password.")
攻撃手法:
同様に、username
フィールドに' or '1'='1
、password
フィールドに' or '1'='1
を入力すると、常にtrue
を返すクエリが生成され、認証が突破されます。
脆弱なコード:
const fs = require('fs');
const xpath = require('xpath');
const dom = require('xmldom').DOMParser;
const xml = fs.readFileSync('users.xml', 'utf-8');
const doc = new dom().parseFromString(xml);
const username = req.query.username;
const password = req.query.password;
const query = `//user[username/text()='${username}' and password/text()='${password}']`;
const nodes = xpath.select(query, doc);
if (nodes.length > 0) {
res.send("Login successful!");
} else {
res.send("Invalid username or password.");
}
攻撃手法:
攻撃者は、username
フィールドに' or '1'='1
、password
フィールドに' or '1'='1
を入力することで、任意のユーザーとして認証を通過できます。
脆弱なコード:
import javax.xml.xpath.*;
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
public class XPathInjectionExample {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("users.xml");
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
String username = args[0];
String password = args[1];
String expression = "//user[username/text()='" + username + "' and password/text()='" + password + "']";
XPathExpression expr = xpath.compile(expression);
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
if (nodes.getLength() > 0) {
System.out.println("Login successful!");
} else {
System.out.println("Invalid username or password.");
}
}
}
攻撃手法:
攻撃者がusername
として' or '1'='1
、password
として' or '1'='1
を提供することで、XPathクエリが改ざんされ、認証を突破することができます。
例えば、Pythonでは以下のように構築します。
query = ".//user[username=? and password=?]"
result = root.findall(query, {'username': username, 'password': password})
'
, "
, &
, <
, >
, など)をエスケープし、意図しないクエリの改ざんを防ぎます。まとめ: XPathインジェクション攻撃は、XMLデータベースや文書に対して不正なクエリを実行するための脆弱性です。パラメータ化されたクエリの使用、入力のサニタイズ、ホワイトリスト方式の導入などの防止策を実装することで、この脆弱性を効果的に防ぐことが可能です。どのプラットフォームや言語でも、これらのベストプラクティスを適用することが推奨されます。