XPath Injection Vulnerability
XPathインジェクションの脆弱性
説明
XPathインジェクションは、XMLデータをクエリするためにXPathを使用するアプリケーションを標的とするインジェクション攻撃の一種です。これは、攻撃者が悪意のある入力をXPathクエリにインジェクトした際に発生し、機密データへの不正アクセス、データの変更、あるいはシステムの完全な侵害につながる可能性があります。この脆弱性は、認証メカニズムのバイパス、任意のコードの実行、機密情報へのアクセスなどの目的で攻撃者に悪用される恐れがあります。
void _fetch_data(String _searchQuery) {
final content = XmlDocument.parse(xmlFileContent);
final xml_node = XmlXPath.node(content);
final xpath = xml_node.query('//book[author=$_searchQuery');
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Search Result'),
content: Text(result),
),
);
}
import Foundation
import SWXMLHash
func main() {
print("Enter search term:")
let searchTerm = readLine()!
let xml = SWXMLHash.parse(xmlString)
let results = xml["books"]["book"].all(withAttribute: "title", matchingXPath: "//title[contains(text(), '\(searchTerm)')]")
for result in results {
print(result["title"].element!.text)
print(result["author"].element!.text)
}
}
import javax.xml.parsers.DocumentBuilderFactory
fun main() {
val userInput = readLine() ?: return
val xpathQuery = "//*[username/text()='${userInput}']"
val xmlData = """
<users>
<user>
<username>Alice</username>
<password>pass123</password>
</user>
<user>
<username>Bob</username>
<password>pass456</password>
</user>
</users>
""".trimIndent()
val xpath = XPathFactory.newInstance().newXPath()
val result = xpath.evaluate(xpathQuery, xmlData)
}
推奨事項
XPathインジェクションの脆弱性を軽減するためには、以下の対策が重要です。
- ユーザー入力をクエリのロジックから分離する、パラメータ化されたクエリ(プレースホルダ)またはプリペアドステートメントを使用する。
- ユーザー入力をXPathクエリで使用する前に、適切に検証およびサニタイズ(無害化)する。
bool _validate_query(String _searchQuery){
// check for special characters
for(var i = 0; i < tokens.length; i++){
if (string.contains(new RegExp(r'[A-Z]')) == false){
return false;
}
}
return true;
}
void _fetch_data(String _searchQuery) {
// validate user input
if (_validate_query(_searchQuery) == false){
// raise error
return ;
}
final content = XmlDocument.parse(xmlFileContent);
final xml_node = XmlXPath.node(content);
final xpath = xml_node.query('//book[author=$_searchQuery');
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Search Result'),
content: Text(result),
),
);
}
import Foundation
import SWXMLHash
func main() {
print("Enter search term:")
guard let searchTerm = readLine()?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
print("Invalid search term")
return
}
let xml = SWXMLHash.parse(xmlString)
let results = xml["books"]["book"].all(withAttribute: "title", matchingXPath: "//title[contains(text(), '\(searchTerm)')]")
for result in results {
print(result["title"].element!.text)
print(result["author"].element!.text)
}
}
fun sanitize(input: String): String {
// Replace all XPath special characters with their HTML entities
return input.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace(""", """)
.replace("'", "'")
}
fun main() {
val userInput = readLine() ?: return
val xmlData = """
<users>
<user>
<username>Alice</username>
<password>pass123</password>
</user>
<user>
<username>Bob</username>
<password>pass456</password>
</user>
</users>
""".trimIndent()
val sanitizedInput = sanitize(userInput)
val xpathQuery = "//*[username/text()='${sanitizedInput}']"
val xpath = XPathFactory.newInstance().newXPath()
val expression = xpath.compile(xpathQuery)
val result = expression.evaluate(xmlData, XPathConstants.NODESET)
val nodeList = result as? List<*> ?: emptyList<Any>()
val matchedUsers = nodeList.filterIsInstance<org.w3c.dom.Node>()
.map { node -> node.textContent }
.joinToString(", ")
println("Matched users: $matchedUsers")
}
リンク
標準
- OWASP_MASVS_L1:
- MSTG_PLATFORM_2
- OWASP_MASVS_L2:
- MSTG_PLATFORM_2
- CWE_TOP_25:
- CWE_89
- PCI_STANDARDS:
- REQ_2_2
- REQ_6_2
- REQ_6_3
- REQ_11_3
- OWASP_MASVS_v2_1:
- MASVS_CODE_4
- SOC2_CONTROLS:
- CC_2_1
- CC_3_4
- CC_4_1
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5
- HIPAA_CONTROLS:
- SECURITY212
- SECURITY213
- SECURITY255