- 필수 기능
- 시작하기
- Glossary
- 표준 속성
- Guides
- Agent
- 통합
- 개방형텔레메트리
- 개발자
- API
- Datadog Mobile App
- CoScreen
- Cloudcraft
- 앱 내
- 서비스 관리
- 인프라스트럭처
- 애플리케이션 성능
- APM
- Continuous Profiler
- 스팬 시각화
- 데이터 스트림 모니터링
- 데이터 작업 모니터링
- 디지털 경험
- 소프트웨어 제공
- 보안
- AI Observability
- 로그 관리
- 관리
ID: java-security/tainted-xpath
Language: Java
Severity: Warning
Category: Best Practices
CWE: 643
This rule identifies potential security vulnerabilities in your code where an XPath expression may be influenced by data coming from an HTTP request. This could lead to what is known as an XPath Injection attack, where an attacker could manipulate the XPath query to access unauthorized data, or potentially cause other harmful effects.
This rule is crucial because XPath Injection is a severe security risk, similar to SQL Injection. If an attacker can control part of an XPath query, they can alter the query’s logic, leading to unauthorized access or exposure to sensitive data.
Never construct XPath queries using string concatenation with unvalidated input. Instead, always use parameterized queries or sanitize the input before using it in an XPath query. If possible, limit the XPath functionality that your application uses to reduce the attack surface. You can also use APIs that automatically protect against XPath Injection, or use a web application firewall to detect and block attack attempts.
@WebServlet(value = "/xpathi-00/BenchmarkTest01223")
public class BenchmarkTest01223 extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String param = "";
java.util.Enumeration<String> headers = request.getHeaders("BenchmarkTest01223");
if (headers != null && headers.hasMoreElements()) {
param = headers.nextElement(); // just grab first element
}
// URL Decode the header value since req.getHeaders() doesn't. Unlike req.getParameters().
param = java.net.URLDecoder.decode(param, "UTF-8");
String bar = new Test().doSomething(request, param);
try {
java.io.FileInputStream file =
new java.io.FileInputStream(
org.owasp.benchmark.helpers.Utils.getFileFromClasspath(
"employees.xml", this.getClass().getClassLoader()));
javax.xml.parsers.DocumentBuilderFactory builderFactory =
javax.xml.parsers.DocumentBuilderFactory.newInstance();
// Prevent XXE
builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
javax.xml.parsers.DocumentBuilder builder = builderFactory.newDocumentBuilder();
org.w3c.dom.Document xmlDocument = builder.parse(file);
javax.xml.xpath.XPathFactory xpf = javax.xml.xpath.XPathFactory.newInstance();
javax.xml.xpath.XPath xp = xpf.newXPath();
String expression = "/Employees/Employee[@emplid='" + bar + "']";
xp.compile(expression).evaluate(xmlDocument, javax.xml.xpath.XPathConstants.NODESET);
response.getWriter().println("Your query results are: <br/>");
for (int i = 0; i < nodeList.getLength(); i++) {
org.w3c.dom.Element value = (org.w3c.dom.Element) nodeList.item(i);
response.getWriter().println(value.getTextContent() + "<br/>");
}
} catch (javax.xml.xpath.XPathExpressionException
| javax.xml.parsers.ParserConfigurationException
| org.xml.sax.SAXException e) {
response.getWriter()
.println(
"Error parsing XPath input: '"
+ org.owasp.esapi.ESAPI.encoder().encodeForHTML(bar)
+ "'");
throw new ServletException(e);
}
} // end doPost
private class Test {
public String doSomething(HttpServletRequest request, String param)
throws ServletException, IOException {
String bar;
String guess = "ABC";
char switchTarget = guess.charAt(2);
// Simple case statement that assigns param to bar on conditions 'A', 'C', or 'D'
switch (switchTarget) {
case 'A':
bar = param;
break;
case 'B':
bar = "bobs_your_uncle";
break;
case 'C':
case 'D':
bar = param;
break;
default:
bar = "bobs_your_uncle";
break;
}
return bar;
}
} // end innerclass Test
} // end DataflowThruInnerClass
@WebServlet(value = "/xpathi-00/BenchmarkTest01223")
public class BenchmarkTest01223 extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String param = "";
java.util.Enumeration<String> headers = request.getHeaders("BenchmarkTest01223");
if (headers != null && headers.hasMoreElements()) {
param = headers.nextElement(); // just grab first element
}
// URL Decode the header value since req.getHeaders() doesn't. Unlike req.getParameters().
param = java.net.URLDecoder.decode(param, "UTF-8");
String bar = new Test().doSomething(request, param);
try {
java.io.FileInputStream file =
new java.io.FileInputStream(
org.owasp.benchmark.helpers.Utils.getFileFromClasspath(
"employees.xml", this.getClass().getClassLoader()));
javax.xml.parsers.DocumentBuilderFactory builderFactory =
javax.xml.parsers.DocumentBuilderFactory.newInstance();
// Prevent XXE
builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
javax.xml.parsers.DocumentBuilder builder = builderFactory.newDocumentBuilder();
org.w3c.dom.Document xmlDocument = builder.parse(file);
javax.xml.xpath.XPathFactory xpf = javax.xml.xpath.XPathFactory.newInstance();
javax.xml.xpath.XPath xp = xpf.newXPath();
String expression = "/Employees/Employee[@emplid='" + bar + "']";
// ruleid: tainted-xpath-from-http-request
org.w3c.dom.NodeList nodeList = (org.w3c.dom.NodeList) xp.compile(expression).evaluate(xmlDocument, javax.xml.xpath.XPathConstants.NODESET);
response.getWriter().println("Your query results are: <br/>");
for (int i = 0; i < nodeList.getLength(); i++) {
org.w3c.dom.Element value = (org.w3c.dom.Element) nodeList.item(i);
response.getWriter().println(value.getTextContent() + "<br/>");
}
} catch (javax.xml.xpath.XPathExpressionException
| javax.xml.parsers.ParserConfigurationException
| org.xml.sax.SAXException e) {
response.getWriter()
.println(
"Error parsing XPath input: '"
+ org.owasp.esapi.ESAPI.encoder().encodeForHTML(bar)
+ "'");
throw new ServletException(e);
}
} // end doPost
private class Test {
public String doSomething(HttpServletRequest request, String param)
throws ServletException, IOException {
String bar;
String guess = "ABC";
char switchTarget = guess.charAt(2);
// Simple case statement that assigns param to bar on conditions 'A', 'C', or 'D'
switch (switchTarget) {
case 'A':
bar = param;
break;
case 'B':
bar = "bobs_your_uncle";
break;
case 'C':
case 'D':
bar = param;
break;
default:
bar = "bobs_your_uncle";
break;
}
return bar;
}
} // end innerclass Test
} // end DataflowThruInnerClass
class Class {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
javax.servlet.http.Cookie[] theCookies = request.getCookies();
String param = "noCookieValueSupplied";
if (theCookies != null) {
for (javax.servlet.http.Cookie theCookie : theCookies) {
if (theCookie.getName().equals("BenchmarkTest00118")) {
param = java.net.URLDecoder.decode(theCookie.getValue(), "UTF-8");
break;
}
}
}
String bar;
// Simple if statement that assigns constant to bar on true condition
int num = 86;
if ((7 * 42) - num > 200) bar = "This_should_always_happen";
else bar = param;
try {
java.io.FileInputStream file =
new java.io.FileInputStream(
org.owasp.benchmark.helpers.Utils.getFileFromClasspath(
"employees.xml", this.getClass().getClassLoader()));
javax.xml.parsers.DocumentBuilderFactory builderFactory =
javax.xml.parsers.DocumentBuilderFactory.newInstance();
// Prevent XXE
builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
javax.xml.parsers.DocumentBuilder builder = builderFactory.newDocumentBuilder();
org.w3c.dom.Document xmlDocument = builder.parse(file);
javax.xml.xpath.XPathFactory xpf = javax.xml.xpath.XPathFactory.newInstance();
javax.xml.xpath.XPath xp = xpf.newXPath();
String expression = "/Employees/Employee[@emplid='" + bar + "']";
String result = xp.evaluate(expression, xmlDocument);
response.getWriter().println("Your query results are: " + result + "<br/>");
} catch (javax.xml.xpath.XPathExpressionException
| javax.xml.parsers.ParserConfigurationException
| org.xml.sax.SAXException e) {
response.getWriter()
.println(
"Error parsing XPath input: '"
+ org.owasp.esapi.ESAPI.encoder().encodeForHTML(bar)
+ "'");
throw new ServletException(e);
}
}
}
class Test {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
javax.servlet.http.Cookie[] theCookies = request.getCookies();
String param = "noCookieValueSupplied";
if (theCookies != null) {
for (javax.servlet.http.Cookie theCookie : theCookies) {
if (theCookie.getName().equals("BenchmarkTest00116")) {
param = java.net.URLDecoder.decode(theCookie.getValue(), "UTF-8");
break;
}
}
}
String bar = "safe!";
java.util.HashMap<String, Object> map51005 = new java.util.HashMap<String, Object>();
map51005.put("keyA-51005", "a_Value"); // put some stuff in the collection
map51005.put("keyB-51005", param); // put it in a collection
map51005.put("keyC", "another_Value"); // put some stuff in the collection
bar = (String) map51005.get("keyB-51005"); // get it back out
bar = (String) map51005.get("keyA-51005"); // get safe value back out
try {
java.io.FileInputStream file =
new java.io.FileInputStream(
org.owasp.benchmark.helpers.Utils.getFileFromClasspath(
"employees.xml", this.getClass().getClassLoader()));
javax.xml.parsers.DocumentBuilderFactory builderFactory =
javax.xml.parsers.DocumentBuilderFactory.newInstance();
// Prevent XXE
builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
javax.xml.parsers.DocumentBuilder builder = builderFactory.newDocumentBuilder();
org.w3c.dom.Document xmlDocument = builder.parse(file);
javax.xml.xpath.XPathFactory xpf = javax.xml.xpath.XPathFactory.newInstance();
javax.xml.xpath.XPath xp = xpf.newXPath();
String expression = "/Employees/Employee[@emplid='" + bar + "']";
org.w3c.dom.NodeList nodeList =
(org.w3c.dom.NodeList)
xp.compile(expression)
.evaluate(xmlDocument, javax.xml.xpath.XPathConstants.NODESET);
response.getWriter().println("Your query results are: <br/>");
for (int i = 0; i < nodeList.getLength(); i++) {
org.w3c.dom.Element value = (org.w3c.dom.Element) nodeList.item(i);
response.getWriter().println(value.getTextContent() + "<br/>");
}
} catch (javax.xml.xpath.XPathExpressionException
| javax.xml.parsers.ParserConfigurationException
| org.xml.sax.SAXException e) {
response.getWriter()
.println(
"Error parsing XPath input: '"
+ org.owasp.esapi.ESAPI.encoder().encodeForHTML(bar)
+ "'");
throw new ServletException(e);
}
}
}
@WebServlet(value = "/xpathi-00/BenchmarkTest00207")
public class BenchmarkTest00207 extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String param = "";
if (request.getHeader("BenchmarkTest00207") != null) {
param = request.getHeader("BenchmarkTest00207");
}
// URL Decode the header value since req.getHeader() doesn't. Unlike req.getParameter().
param = java.net.URLDecoder.decode(param, "UTF-8");
String bar = "";
if (param != null) {
bar =
new String(
org.apache.commons.codec.binary.Base64.decodeBase64(
org.apache.commons.codec.binary.Base64.encodeBase64(
param.getBytes())));
}
try {
java.io.FileInputStream file =
new java.io.FileInputStream(
org.owasp.benchmark.helpers.Utils.getFileFromClasspath(
"employees.xml", this.getClass().getClassLoader()));
javax.xml.parsers.DocumentBuilderFactory builderFactory =
javax.xml.parsers.DocumentBuilderFactory.newInstance();
// Prevent XXE
builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
javax.xml.parsers.DocumentBuilder builder = builderFactory.newDocumentBuilder();
org.w3c.dom.Document xmlDocument = builder.parse(file);
javax.xml.xpath.XPathFactory xpf = javax.xml.xpath.XPathFactory.newInstance();
javax.xml.xpath.XPath xp = xpf.newXPath();
String expression = "/Employees/Employee[@emplid='1234']";
String result = xp.evaluate(expression, xmlDocument);
response.getWriter().println("Your query results are: " + result + "<br/>");
} catch (javax.xml.xpath.XPathExpressionException
| javax.xml.parsers.ParserConfigurationException
| org.xml.sax.SAXException e) {
response.getWriter()
.println(
"Error parsing XPath input: '"
+ org.owasp.esapi.ESAPI.encoder().encodeForHTML(bar)
+ "'");
throw new ServletException(e);
}
}
}