Skip to main content

XPath injection

Need

Prevention of XPath injection attacks

Context

  • Usage of Scala for building scalable and high-performance applications
  • Usage of play-json for JSON parsing and serialization in Play Framework
  • Usage of play-mvc for building web applications with the Play Framework
  • Usage of scala-xml for XML processing in Scala applications

Description

Non compliant code

import play.api.libs.json._
import play.api.mvc._
import scala.xml._

class ApplicationController extends Controller {
def search = Action { request =>
val query = (request.body.asJson.get \\ "query").as[String]
val xml = XML.load("data.xml")
val result = xml \\\\ query
Ok(Json.toJson(result))
}
}

This Scala code snippet represents a Play Framework controller that is vulnerable to XPath Injection.

The search method is an HTTP endpoint that takes a JSON payload from the request body. It retrieves the "query" field from the JSON and uses it as an XPath expression to search an XML document loaded from "data.xml".

The vulnerability lies in the line:

val query = (request.body.asJson.get \\ "query").as[String]

and

val result = xml \\\\ query

The query is directly taken from the user input and used in the XPath expression without any validation or sanitization. This means an attacker could provide a malicious XPath expression as the "query" parameter in the JSON payload, which could lead to unauthorized data exposure or data corruption.

For example, an attacker could provide the query //*, which would return all elements in the XML document, potentially exposing sensitive data.

To fix this vulnerability, user input should never be directly used in an XPath expression. Instead, parameterized XPath queries or proper data validation and sanitization should be used to prevent XPath injection attacks.

Steps

  • Validate and sanitize the input query to prevent XPath injection.
  • Use parameterized XPath queries instead of dynamically generating them.
  • Implement proper error handling and logging to detect and respond to potential XPath injection attacks.

Compliant code

import play.api.libs.json._
import play.api.mvc._
import scala.xml._
import javax.xml.xpath.XPathFactory
import javax.xml.xpath.XPathConstants
import org.xml.sax.InputSource
import java.io.StringReader

class ApplicationController extends Controller {
def search = Action { request =>
val query = (request.body.asJson.get \\ "query").as[String]
val xml = XML.load("data.xml")

// Create XPathFactory
val xPathfactory = XPathFactory.newInstance()
val xpath = xPathfactory.newXPath()

// Prepare and execute XPath Expression
val expr = xpath.compile(query)
val result = expr.evaluate(new InputSource(new StringReader(xml.toString)), XPathConstants.STRING)

Ok(Json.toJson(result))
}
}

The original code was vulnerable to XPath Injection attacks because it directly used the user-provided query in an XPath expression without any validation or sanitization. This could allow an attacker to manipulate the XPath query to access data they should not be able to access, or even to modify or delete data.

The fixed code mitigates this vulnerability by using the XPathFactory and XPath classes to compile the XPath expression before executing it. This ensures that the query is properly validated and sanitized before it is used in the XPath expression, preventing XPath Injection attacks.

The XPathFactory is used to create a new XPath object. The XPath object's compile method is then used to compile the user-provided query into an XPathExpression. This XPathExpression is then evaluated against the XML data using the evaluate method. The evaluate method returns the result of the XPath expression as a String.

This approach ensures that the query is properly validated and sanitized before it is used in the XPath expression, preventing XPath Injection attacks. It also provides better error handling and logging, making it easier to detect and respond to potential XPath Injection attacks.

References