2
2
import java .io .StringReader ;
3
3
4
4
import javax .servlet .http .HttpServletRequest ;
5
+ import javax .xml .namespace .QName ;
5
6
import javax .xml .parsers .DocumentBuilder ;
6
7
import javax .xml .parsers .DocumentBuilderFactory ;
7
8
import javax .xml .xpath .XPath ;
8
9
import javax .xml .xpath .XPathConstants ;
9
10
import javax .xml .xpath .XPathExpression ;
11
+ import javax .xml .xpath .XPathExpressionException ;
10
12
import javax .xml .xpath .XPathFactory ;
11
13
12
14
import org .w3c .dom .Document ;
13
15
import org .xml .sax .InputSource ;
14
16
15
17
public class A {
18
+ private static abstract class XPathImplStub implements XPath {
19
+ public static XPathImplStub getInstance () {
20
+ return null ;
21
+ }
22
+
23
+ @ Override
24
+ public XPathExpression compile (String expression ) throws XPathExpressionException {
25
+ return null ;
26
+ }
27
+
28
+ @ Override
29
+ public Object evaluate (String expression , Object item , QName returnType ) throws XPathExpressionException {
30
+ return null ;
31
+ }
32
+
33
+ @ Override
34
+ public String evaluate (String expression , Object item ) throws XPathExpressionException {
35
+ return null ;
36
+ }
37
+
38
+ @ Override
39
+ public Object evaluate (String expression , InputSource source , QName returnType )
40
+ throws XPathExpressionException {
41
+ return null ;
42
+ }
43
+
44
+ @ Override
45
+ public String evaluate (String expression , InputSource source ) throws XPathExpressionException {
46
+ return null ;
47
+ }
48
+
49
+ }
50
+
16
51
public void handle (HttpServletRequest request ) throws Exception {
17
52
final String xmlStr = "<users>" + " <user name=\" aaa\" pass=\" pass1\" ></user>"
18
53
+ " <user name=\" bbb\" pass=\" pass2\" ></user>" + "</users>" ;
19
54
DocumentBuilderFactory domFactory = DocumentBuilderFactory .newInstance ();
20
55
domFactory .setNamespaceAware (true );
21
56
DocumentBuilder builder = domFactory .newDocumentBuilder ();
22
- Document doc = builder .parse (new InputSource (new StringReader (xmlStr )));
57
+ InputSource xmlSource = new InputSource (new StringReader (xmlStr ));
58
+ Document doc = builder .parse (xmlSource );
23
59
24
60
XPathFactory factory = XPathFactory .newInstance ();
25
61
XPath xpath = factory .newXPath ();
62
+ XPathImplStub xpathStub = XPathImplStub .getInstance ();
26
63
27
64
// Injectable data
28
65
String user = request .getParameter ("user" );
@@ -31,9 +68,13 @@ public void handle(HttpServletRequest request) throws Exception {
31
68
// Bad expression
32
69
String expression1 = "/users/user[@name='" + user + "' and @pass='" + pass + "']" ;
33
70
xpath .evaluate (expression1 , doc , XPathConstants .BOOLEAN ); // $hasXPathInjection
71
+ xpathStub .evaluate (expression1 , doc , XPathConstants .BOOLEAN ); // $hasXPathInjection
72
+ xpath .evaluateExpression (expression1 , xmlSource ); // $hasXPathInjection
73
+ xpathStub .evaluateExpression (expression1 , xmlSource ); // $hasXPathInjection
34
74
35
75
// Bad expression
36
76
XPathExpression expression2 = xpath .compile ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
77
+ xpathStub .compile ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
37
78
expression2 .evaluate (doc , XPathConstants .BOOLEAN );
38
79
39
80
// Bad expression
@@ -44,6 +85,7 @@ public void handle(HttpServletRequest request) throws Exception {
44
85
sb .append ("']" );
45
86
String query = sb .toString ();
46
87
XPathExpression expression3 = xpath .compile (query ); // $hasXPathInjection
88
+ xpathStub .compile (query ); // $hasXPathInjection
47
89
expression3 .evaluate (doc , XPathConstants .BOOLEAN );
48
90
49
91
// Good expression
@@ -63,9 +105,14 @@ public void handle(HttpServletRequest request) throws Exception {
63
105
// Bad Dom4j
64
106
org .dom4j .io .SAXReader reader = new org .dom4j .io .SAXReader ();
65
107
org .dom4j .Document document = reader .read (new ByteArrayInputStream (xmlStr .getBytes ()));
66
- document .selectSingleNode ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ) // $hasXPathInjection
67
- .hasContent ();
108
+ document .selectObject ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
68
109
document .selectNodes ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
110
+ document .selectNodes ("/users/user[@name='test']" , "/users/user[@pass='" + pass + "']" ); // Safe-ish
111
+ document .selectSingleNode ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
112
+ document .valueOf ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
113
+ document .numberValueOf ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
114
+ document .matches ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
115
+ document .createXPath ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
69
116
}
70
117
}
71
118
}
0 commit comments