1+ import javax .xml .*;
2+
3+ import org .w3c .dom .Document ;
4+ import org .xml .sax .InputSource ;
5+ import org .xml .sax .SAXException ;
6+
7+ import javax .xml .parsers .DocumentBuilder ;
8+ import javax .xml .parsers .DocumentBuilderFactory ;
9+ import javax .xml .parsers .ParserConfigurationException ;
10+ import javax .xml .xpath .XPath ;
11+ import javax .xml .xpath .XPathConstants ;
12+ import javax .xml .xpath .XPathExpression ;
13+ import javax .xml .xpath .XPathExpressionException ;
14+ import javax .xml .xpath .XPathFactory ;
15+
16+ import java .io .BufferedInputStream ;
17+ import java .io .ByteArrayInputStream ;
18+ import java .io .InputStream ;
19+ import java .io .StringReader ;
20+
21+ import javax .servlet .http .HttpServletRequest ;
22+
23+ public class A {
24+ public void handle (HttpServletRequest request ) throws Exception {
25+ final String xmlStr = "<users>" + " <user name=\" aaa\" pass=\" pass1\" ></user>"
26+ + " <user name=\" bbb\" pass=\" pass2\" ></user>" + "</users>" ;
27+ DocumentBuilderFactory domFactory = DocumentBuilderFactory .newInstance ();
28+ domFactory .setNamespaceAware (true );
29+ DocumentBuilder builder = domFactory .newDocumentBuilder ();
30+ Document doc = builder .parse (new InputSource (new StringReader (xmlStr )));
31+
32+ XPathFactory factory = XPathFactory .newInstance ();
33+ XPath xpath = factory .newXPath ();
34+
35+ // Injectable data
36+ String user = request .getParameter ("user" );
37+ String pass = request .getParameter ("pass" );
38+ if (user != null && pass != null ) {
39+ boolean isExist = false ;
40+
41+ // Bad expression
42+ String expression1 = "/users/user[@name='" + user + "' and @pass='" + pass + "']" ;
43+ isExist = (boolean ) xpath .evaluate (expression1 , doc , XPathConstants .BOOLEAN ); // $hasXPathInjection
44+ System .out .println (isExist );
45+
46+ // Bad expression
47+ XPathExpression expression2 = xpath .compile ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
48+ isExist = (boolean ) expression2 .evaluate (doc , XPathConstants .BOOLEAN );
49+ System .out .println (isExist );
50+
51+ // Bad expression
52+ StringBuffer sb = new StringBuffer ("/users/user[@name=" );
53+ sb .append (user );
54+ sb .append ("' and @pass='" );
55+ sb .append (pass );
56+ sb .append ("']" );
57+ String query = sb .toString ();
58+ XPathExpression expression3 = xpath .compile (query ); // $hasXPathInjection
59+ isExist = (boolean ) expression3 .evaluate (doc , XPathConstants .BOOLEAN );
60+ System .out .println (isExist );
61+
62+ // Good expression
63+ String expression4 = "/users/user[@name=$user and @pass=$pass]" ;
64+ xpath .setXPathVariableResolver (v -> {
65+ switch (v .getLocalPart ()) {
66+ case "user" :
67+ return user ;
68+ case "pass" :
69+ return pass ;
70+ default :
71+ throw new IllegalArgumentException ();
72+ }
73+ });
74+ isExist = (boolean ) xpath .evaluate (expression4 , doc , XPathConstants .BOOLEAN );
75+ System .out .println (isExist );
76+
77+ // Bad Dom4j
78+ org .dom4j .io .SAXReader reader = new org .dom4j .io .SAXReader ();
79+ org .dom4j .Document document = reader .read (new ByteArrayInputStream (xmlStr .getBytes ()));
80+ isExist = document .selectSingleNode ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ) // $hasXPathInjection
81+ .hasContent ();
82+ document .selectNodes ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
83+ }
84+ }
85+ }
0 commit comments