11
11
import javax .xml .xpath .XPathExpressionException ;
12
12
import javax .xml .xpath .XPathFactory ;
13
13
14
+ import org .dom4j .DocumentFactory ;
15
+ import org .dom4j .DocumentHelper ;
16
+ import org .dom4j .Namespace ;
17
+ import org .dom4j .io .SAXReader ;
18
+ import org .dom4j .util .ProxyDocumentFactory ;
19
+ import org .dom4j .xpath .DefaultXPath ;
20
+ import org .dom4j .xpath .XPathPattern ;
14
21
import org .w3c .dom .Document ;
15
22
import org .xml .sax .InputSource ;
16
23
@@ -48,71 +55,86 @@ public String evaluate(String expression, InputSource source) throws XPathExpres
48
55
49
56
}
50
57
58
+ private static class ProxyDocumentFactoryStub extends ProxyDocumentFactory {
59
+ }
60
+
51
61
public void handle (HttpServletRequest request ) throws Exception {
62
+ String user = request .getParameter ("user" );
63
+ String pass = request .getParameter ("pass" );
64
+ String expression = "/users/user[@name='" + user + "' and @pass='" + pass + "']" ;
65
+
52
66
final String xmlStr = "<users>" + " <user name=\" aaa\" pass=\" pass1\" ></user>"
53
67
+ " <user name=\" bbb\" pass=\" pass2\" ></user>" + "</users>" ;
54
68
DocumentBuilderFactory domFactory = DocumentBuilderFactory .newInstance ();
55
- domFactory .setNamespaceAware (true );
56
69
DocumentBuilder builder = domFactory .newDocumentBuilder ();
57
70
InputSource xmlSource = new InputSource (new StringReader (xmlStr ));
58
71
Document doc = builder .parse (xmlSource );
59
72
60
73
XPathFactory factory = XPathFactory .newInstance ();
61
74
XPath xpath = factory .newXPath ();
62
- XPathImplStub xpathStub = XPathImplStub .getInstance ();
63
75
64
- // Injectable data
65
- String user = request .getParameter ("user" );
66
- String pass = request .getParameter ("pass" );
67
- if (user != null && pass != null ) {
68
- // Bad expression
69
- String expression1 = "/users/user[@name='" + user + "' and @pass='" + pass + "']" ;
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
74
-
75
- // Bad expression
76
- XPathExpression expression2 = xpath .compile ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
77
- xpathStub .compile ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
78
- expression2 .evaluate (doc , XPathConstants .BOOLEAN );
79
-
80
- // Bad expression
81
- StringBuffer sb = new StringBuffer ("/users/user[@name=" );
82
- sb .append (user );
83
- sb .append ("' and @pass='" );
84
- sb .append (pass );
85
- sb .append ("']" );
86
- String query = sb .toString ();
87
- XPathExpression expression3 = xpath .compile (query ); // $hasXPathInjection
88
- xpathStub .compile (query ); // $hasXPathInjection
89
- expression3 .evaluate (doc , XPathConstants .BOOLEAN );
90
-
91
- // Good expression
92
- String expression4 = "/users/user[@name=$user and @pass=$pass]" ;
93
- xpath .setXPathVariableResolver (v -> {
94
- switch (v .getLocalPart ()) {
95
- case "user" :
96
- return user ;
97
- case "pass" :
98
- return pass ;
99
- default :
100
- throw new IllegalArgumentException ();
101
- }
102
- });
103
- xpath .evaluate (expression4 , doc , XPathConstants .BOOLEAN ); // Safe
104
-
105
- // Bad Dom4j
106
- org .dom4j .io .SAXReader reader = new org .dom4j .io .SAXReader ();
107
- org .dom4j .Document document = reader .read (new ByteArrayInputStream (xmlStr .getBytes ()));
108
- document .selectObject ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
109
- document .selectNodes ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
110
- document .selectNodes ("/users/user[@name='test']" , "/users/user[@pass='" + pass + "']" ); // $hasXPathInjection
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
116
- }
76
+ xpath .evaluate (expression , doc , XPathConstants .BOOLEAN ); // $hasXPathInjection
77
+ xpath .evaluateExpression (expression , xmlSource ); // $hasXPathInjection
78
+ xpath .compile ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
79
+
80
+ XPathImplStub xpathStub = XPathImplStub .getInstance ();
81
+ xpathStub .evaluate (expression , doc , XPathConstants .BOOLEAN ); // $hasXPathInjection
82
+ xpathStub .evaluateExpression (expression , xmlSource ); // $hasXPathInjection
83
+ xpathStub .compile ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
84
+
85
+ StringBuffer sb = new StringBuffer ("/users/user[@name=" );
86
+ sb .append (user );
87
+ sb .append ("' and @pass='" );
88
+ sb .append (pass );
89
+ sb .append ("']" );
90
+ String query = sb .toString ();
91
+
92
+ xpath .compile (query ); // $hasXPathInjection
93
+ xpathStub .compile (query ); // $hasXPathInjection
94
+
95
+ String expression4 = "/users/user[@name=$user and @pass=$pass]" ;
96
+ xpath .setXPathVariableResolver (v -> {
97
+ switch (v .getLocalPart ()) {
98
+ case "user" :
99
+ return user ;
100
+ case "pass" :
101
+ return pass ;
102
+ default :
103
+ throw new IllegalArgumentException ();
104
+ }
105
+ });
106
+ xpath .evaluate (expression4 , doc , XPathConstants .BOOLEAN ); // Safe
107
+
108
+ SAXReader reader = new SAXReader ();
109
+ org .dom4j .Document document = reader .read (new ByteArrayInputStream (xmlStr .getBytes ()));
110
+ document .selectObject ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
111
+ document .selectNodes ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
112
+ document .selectNodes ("/users/user[@name='test']" , "/users/user[@pass='" + pass + "']" ); // $hasXPathInjection
113
+ document .selectSingleNode ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
114
+ document .valueOf ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
115
+ document .numberValueOf ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
116
+ document .matches ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
117
+ document .createXPath ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
118
+
119
+ new DefaultXPath ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
120
+ new XPathPattern ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
121
+
122
+ DocumentFactory docFactory = DocumentFactory .getInstance ();
123
+ docFactory .createPattern ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
124
+ docFactory .createXPath ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
125
+ docFactory .createXPathFilter ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
126
+
127
+ DocumentHelper .createPattern ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
128
+ DocumentHelper .createXPath ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
129
+ DocumentHelper .createXPathFilter ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
130
+
131
+ ProxyDocumentFactoryStub proxyDocFactory = new ProxyDocumentFactoryStub ();
132
+ proxyDocFactory .createPattern ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
133
+ proxyDocFactory .createXPath ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
134
+ proxyDocFactory .createXPathFilter ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
135
+
136
+ Namespace namespace = new Namespace ("prefix" , "http://some.uri.io" );
137
+ namespace .createPattern ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
138
+ namespace .createXPathFilter ("/users/user[@name='" + user + "' and @pass='" + pass + "']" ); // $hasXPathInjection
117
139
}
118
140
}
0 commit comments