Skip to content

XPath Injection Vulnerability

XPath Injection Vulnerability

Description

XPath Injection is a type of injection attack targeting applications that use XPath to query XML data. It occurs when an attacker injects malicious input into an XPath query, which can lead to unauthorized access to sensitive data, modification of data, or even complete system compromise. This vulnerability can be exploited by attackers to bypass authentication mechanisms, execute arbitrary code, and gain access to sensitive information.

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)
}

Recommendation

To mitigate XPath Injection vulnerabilities, it is important to:

  • Use parameterized queries or prepared statements, which separate the user input from the query logic.
  • Properly validate and sanitize user input before using it in XPath queries.
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("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace(""", "&quot;")
                .replace("'", "&apos;")
}

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")
}

Standards

  • 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