Skip to content

Commit 22e741c

Browse files
committed
*)add XQExpression.executeCommand(0) sink
1 parent a6a0fa2 commit 22e741c

File tree

6 files changed

+112
-52
lines changed

6 files changed

+112
-52
lines changed

java/ql/src/Security/CWE/CWE-652/XQueryInjection.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ public void bad1(HttpServletRequest request) throws XQException {
3232
}
3333
}
3434

35+
public void bad2(HttpServletRequest request) throws XQException {
36+
String name = request.getParameter("name");
37+
XQDataSource xqds = new SaxonXQDataSource();
38+
XQConnection conn = xqds.getConnection();
39+
XQExpression expr = conn.createExpression();
40+
//bad code
41+
expr.executeCommand(name);
42+
}
43+
3544
public void good(HttpServletRequest request) throws XQException {
3645
String name = request.getParameter("name");
3746
XQDataSource ds = new SaxonXQDataSource();

java/ql/src/Security/CWE/CWE-652/XQueryInjection.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ class XQueryInjectionConfig extends TaintTracking::Configuration {
2525

2626
override predicate isSink(DataFlow::Node sink) {
2727
sink.asExpr() = any(XQueryPreparedExecuteCall xpec).getPreparedExpression() or
28-
sink.asExpr() = any(XQueryExecuteCall xec).getExecuteQueryArgument()
28+
sink.asExpr() = any(XQueryExecuteCall xec).getExecuteQueryArgument() or
29+
sink.asExpr() = any(XQueryExecuteCommandCall xecc).getExecuteCommandArgument()
2930
}
3031

3132
/**

java/ql/src/Security/CWE/CWE-652/XQueryInjectionLib.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,19 @@ class XQueryExecuteCall extends MethodAccess {
5050
/** Return this execute query argument. */
5151
Expr getExecuteQueryArgument() { result = this.getArgument(0) }
5252
}
53+
54+
/** A call to `XQExpression.executeCommand`. */
55+
class XQueryExecuteCommandCall extends MethodAccess {
56+
XQueryExecuteCommandCall() {
57+
exists(Method m |
58+
this.getMethod() = m and
59+
m.hasName("executeCommand") and
60+
m.getDeclaringType()
61+
.getASourceSupertype*()
62+
.hasQualifiedName("javax.xml.xquery", "XQExpression")
63+
)
64+
}
65+
66+
/** Return this execute command argument. */
67+
Expr getExecuteCommandArgument() { result = this.getArgument(0) }
68+
}
Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,43 @@
11
edges
2-
| XQueryInjection.java:42:23:42:50 | getParameter(...) : String | XQueryInjection.java:47:35:47:38 | xqpe |
3-
| XQueryInjection.java:55:23:55:50 | getParameter(...) : String | XQueryInjection.java:60:53:60:57 | query |
4-
| XQueryInjection.java:68:32:68:59 | nameStr : String | XQueryInjection.java:73:35:73:38 | xqpe |
5-
| XQueryInjection.java:80:33:80:60 | nameStr : String | XQueryInjection.java:85:53:85:57 | query |
6-
| XQueryInjection.java:93:28:93:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:97:35:97:38 | xqpe |
7-
| XQueryInjection.java:105:28:105:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:109:53:109:56 | name |
8-
| XQueryInjection.java:117:28:117:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:122:35:122:38 | xqpe |
9-
| XQueryInjection.java:130:28:130:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:135:53:135:54 | br |
2+
| XQueryInjection.java:45:23:45:50 | getParameter(...) : String | XQueryInjection.java:51:35:51:38 | xqpe |
3+
| XQueryInjection.java:59:23:59:50 | getParameter(...) : String | XQueryInjection.java:65:53:65:57 | query |
4+
| XQueryInjection.java:73:32:73:59 | nameStr : String | XQueryInjection.java:79:35:79:38 | xqpe |
5+
| XQueryInjection.java:86:33:86:60 | nameStr : String | XQueryInjection.java:92:53:92:57 | query |
6+
| XQueryInjection.java:100:28:100:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:104:35:104:38 | xqpe |
7+
| XQueryInjection.java:112:28:112:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:116:53:116:56 | name |
8+
| XQueryInjection.java:124:28:124:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:129:35:129:38 | xqpe |
9+
| XQueryInjection.java:137:28:137:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:142:53:142:54 | br |
10+
| XQueryInjection.java:150:23:150:50 | getParameter(...) : String | XQueryInjection.java:155:29:155:32 | name |
11+
| XQueryInjection.java:157:26:157:49 | getInputStream(...) : ServletInputStream | XQueryInjection.java:159:29:159:30 | br |
1012
nodes
11-
| XQueryInjection.java:42:23:42:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
12-
| XQueryInjection.java:47:35:47:38 | xqpe | semmle.label | xqpe |
13-
| XQueryInjection.java:55:23:55:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
14-
| XQueryInjection.java:60:53:60:57 | query | semmle.label | query |
15-
| XQueryInjection.java:68:32:68:59 | nameStr : String | semmle.label | nameStr : String |
16-
| XQueryInjection.java:73:35:73:38 | xqpe | semmle.label | xqpe |
17-
| XQueryInjection.java:80:33:80:60 | nameStr : String | semmle.label | nameStr : String |
18-
| XQueryInjection.java:85:53:85:57 | query | semmle.label | query |
19-
| XQueryInjection.java:93:28:93:51 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
20-
| XQueryInjection.java:97:35:97:38 | xqpe | semmle.label | xqpe |
21-
| XQueryInjection.java:105:28:105:51 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
22-
| XQueryInjection.java:109:53:109:56 | name | semmle.label | name |
23-
| XQueryInjection.java:117:28:117:51 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
24-
| XQueryInjection.java:122:35:122:38 | xqpe | semmle.label | xqpe |
25-
| XQueryInjection.java:130:28:130:51 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
26-
| XQueryInjection.java:135:53:135:54 | br | semmle.label | br |
13+
| XQueryInjection.java:45:23:45:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
14+
| XQueryInjection.java:51:35:51:38 | xqpe | semmle.label | xqpe |
15+
| XQueryInjection.java:59:23:59:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
16+
| XQueryInjection.java:65:53:65:57 | query | semmle.label | query |
17+
| XQueryInjection.java:73:32:73:59 | nameStr : String | semmle.label | nameStr : String |
18+
| XQueryInjection.java:79:35:79:38 | xqpe | semmle.label | xqpe |
19+
| XQueryInjection.java:86:33:86:60 | nameStr : String | semmle.label | nameStr : String |
20+
| XQueryInjection.java:92:53:92:57 | query | semmle.label | query |
21+
| XQueryInjection.java:100:28:100:51 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
22+
| XQueryInjection.java:104:35:104:38 | xqpe | semmle.label | xqpe |
23+
| XQueryInjection.java:112:28:112:51 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
24+
| XQueryInjection.java:116:53:116:56 | name | semmle.label | name |
25+
| XQueryInjection.java:124:28:124:51 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
26+
| XQueryInjection.java:129:35:129:38 | xqpe | semmle.label | xqpe |
27+
| XQueryInjection.java:137:28:137:51 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
28+
| XQueryInjection.java:142:53:142:54 | br | semmle.label | br |
29+
| XQueryInjection.java:150:23:150:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
30+
| XQueryInjection.java:155:29:155:32 | name | semmle.label | name |
31+
| XQueryInjection.java:157:26:157:49 | getInputStream(...) : ServletInputStream | semmle.label | getInputStream(...) : ServletInputStream |
32+
| XQueryInjection.java:159:29:159:30 | br | semmle.label | br |
2733
#select
28-
| XQueryInjection.java:47:35:47:38 | xqpe | XQueryInjection.java:42:23:42:50 | getParameter(...) : String | XQueryInjection.java:47:35:47:38 | xqpe | XQuery query might include code from $@. | XQueryInjection.java:42:23:42:50 | getParameter(...) | this user input |
29-
| XQueryInjection.java:60:53:60:57 | query | XQueryInjection.java:55:23:55:50 | getParameter(...) : String | XQueryInjection.java:60:53:60:57 | query | XQuery query might include code from $@. | XQueryInjection.java:55:23:55:50 | getParameter(...) | this user input |
30-
| XQueryInjection.java:73:35:73:38 | xqpe | XQueryInjection.java:68:32:68:59 | nameStr : String | XQueryInjection.java:73:35:73:38 | xqpe | XQuery query might include code from $@. | XQueryInjection.java:68:32:68:59 | nameStr | this user input |
31-
| XQueryInjection.java:85:53:85:57 | query | XQueryInjection.java:80:33:80:60 | nameStr : String | XQueryInjection.java:85:53:85:57 | query | XQuery query might include code from $@. | XQueryInjection.java:80:33:80:60 | nameStr | this user input |
32-
| XQueryInjection.java:97:35:97:38 | xqpe | XQueryInjection.java:93:28:93:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:97:35:97:38 | xqpe | XQuery query might include code from $@. | XQueryInjection.java:93:28:93:51 | getInputStream(...) | this user input |
33-
| XQueryInjection.java:109:53:109:56 | name | XQueryInjection.java:105:28:105:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:109:53:109:56 | name | XQuery query might include code from $@. | XQueryInjection.java:105:28:105:51 | getInputStream(...) | this user input |
34-
| XQueryInjection.java:122:35:122:38 | xqpe | XQueryInjection.java:117:28:117:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:122:35:122:38 | xqpe | XQuery query might include code from $@. | XQueryInjection.java:117:28:117:51 | getInputStream(...) | this user input |
35-
| XQueryInjection.java:135:53:135:54 | br | XQueryInjection.java:130:28:130:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:135:53:135:54 | br | XQuery query might include code from $@. | XQueryInjection.java:130:28:130:51 | getInputStream(...) | this user input |
34+
| XQueryInjection.java:51:35:51:38 | xqpe | XQueryInjection.java:45:23:45:50 | getParameter(...) : String | XQueryInjection.java:51:35:51:38 | xqpe | XQuery query might include code from $@. | XQueryInjection.java:45:23:45:50 | getParameter(...) | this user input |
35+
| XQueryInjection.java:65:53:65:57 | query | XQueryInjection.java:59:23:59:50 | getParameter(...) : String | XQueryInjection.java:65:53:65:57 | query | XQuery query might include code from $@. | XQueryInjection.java:59:23:59:50 | getParameter(...) | this user input |
36+
| XQueryInjection.java:79:35:79:38 | xqpe | XQueryInjection.java:73:32:73:59 | nameStr : String | XQueryInjection.java:79:35:79:38 | xqpe | XQuery query might include code from $@. | XQueryInjection.java:73:32:73:59 | nameStr | this user input |
37+
| XQueryInjection.java:92:53:92:57 | query | XQueryInjection.java:86:33:86:60 | nameStr : String | XQueryInjection.java:92:53:92:57 | query | XQuery query might include code from $@. | XQueryInjection.java:86:33:86:60 | nameStr | this user input |
38+
| XQueryInjection.java:104:35:104:38 | xqpe | XQueryInjection.java:100:28:100:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:104:35:104:38 | xqpe | XQuery query might include code from $@. | XQueryInjection.java:100:28:100:51 | getInputStream(...) | this user input |
39+
| XQueryInjection.java:116:53:116:56 | name | XQueryInjection.java:112:28:112:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:116:53:116:56 | name | XQuery query might include code from $@. | XQueryInjection.java:112:28:112:51 | getInputStream(...) | this user input |
40+
| XQueryInjection.java:129:35:129:38 | xqpe | XQueryInjection.java:124:28:124:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:129:35:129:38 | xqpe | XQuery query might include code from $@. | XQueryInjection.java:124:28:124:51 | getInputStream(...) | this user input |
41+
| XQueryInjection.java:142:53:142:54 | br | XQueryInjection.java:137:28:137:51 | getInputStream(...) : ServletInputStream | XQueryInjection.java:142:53:142:54 | br | XQuery query might include code from $@. | XQueryInjection.java:137:28:137:51 | getInputStream(...) | this user input |
42+
| XQueryInjection.java:155:29:155:32 | name | XQueryInjection.java:150:23:150:50 | getParameter(...) : String | XQueryInjection.java:155:29:155:32 | name | XQuery query might include code from $@. | XQueryInjection.java:150:23:150:50 | getParameter(...) | this user input |
43+
| XQueryInjection.java:159:29:159:30 | br | XQueryInjection.java:157:26:157:49 | getInputStream(...) : ServletInputStream | XQueryInjection.java:159:29:159:30 | br | XQuery query might include code from $@. | XQueryInjection.java:157:26:157:49 | getInputStream(...) | this user input |

java/ql/test/experimental/query-tests/security/CWE-652/XQueryInjection.java

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
package com.vuln.v2.controller;
2+
13
import java.io.BufferedReader;
24
import java.io.InputStream;
35
import java.io.InputStreamReader;
@@ -27,9 +29,10 @@ public static void main(String[] args) throws Exception {
2729
+ " for $user in doc(\"users.xml\")/Users/User[name=$name] return $user/password";
2830
conn = xqds.getConnection();
2931
XQExpression expr = conn.createExpression();
30-
expr.bindString(new QName("name"), name, conn.createAtomicType(XQItemType.XQBASETYPE_STRING));
32+
expr.bindString(new QName("name"), name,
33+
conn.createAtomicType(XQItemType.XQBASETYPE_STRING));
3134
XQResultSequence result = expr.executeQuery(query);
32-
while (result.next()){
35+
while (result.next()) {
3336
System.out.println(result.getItemAsString(null));
3437
}
3538
} catch (XQException e) {
@@ -42,10 +45,11 @@ public void testRequestbad(HttpServletRequest request) throws Exception {
4245
String name = request.getParameter("name");
4346
XQDataSource ds = new SaxonXQDataSource();
4447
XQConnection conn = ds.getConnection();
45-
String query = "for $user in doc(\"users.xml\")/Users/User[name='" + name + "'] return $user/password";
48+
String query = "for $user in doc(\"users.xml\")/Users/User[name='" + name
49+
+ "'] return $user/password";
4650
XQPreparedExpression xqpe = conn.prepareExpression(query);
4751
XQResultSequence result = xqpe.executeQuery();
48-
while (result.next()){
52+
while (result.next()) {
4953
System.out.println(result.getItemAsString(null));
5054
}
5155
}
@@ -54,11 +58,12 @@ public void testRequestbad(HttpServletRequest request) throws Exception {
5458
public void testRequestbad1(HttpServletRequest request) throws Exception {
5559
String name = request.getParameter("name");
5660
XQDataSource xqds = new SaxonXQDataSource();
57-
String query = "for $user in doc(\"users.xml\")/Users/User[name='" + name + "'] return $user/password";
61+
String query = "for $user in doc(\"users.xml\")/Users/User[name='" + name
62+
+ "'] return $user/password";
5863
XQConnection conn = xqds.getConnection();
5964
XQExpression expr = conn.createExpression();
6065
XQResultSequence result = expr.executeQuery(query);
61-
while (result.next()){
66+
while (result.next()) {
6267
System.out.println(result.getItemAsString(null));
6368
}
6469
}
@@ -68,22 +73,24 @@ public void testRequestbad1(HttpServletRequest request) throws Exception {
6873
public void testStringtbad(@RequestParam String nameStr) throws XQException {
6974
XQDataSource ds = new SaxonXQDataSource();
7075
XQConnection conn = ds.getConnection();
71-
String query = "for $user in doc(\"users.xml\")/Users/User[name='" + nameStr + "'] return $user/password";
76+
String query = "for $user in doc(\"users.xml\")/Users/User[name='" + nameStr
77+
+ "'] return $user/password";
7278
XQPreparedExpression xqpe = conn.prepareExpression(query);
7379
XQResultSequence result = xqpe.executeQuery();
74-
while (result.next()){
80+
while (result.next()) {
7581
System.out.println(result.getItemAsString(null));
7682
}
7783
}
7884

7985
@RequestMapping
8086
public void testStringtbad1(@RequestParam String nameStr) throws XQException {
8187
XQDataSource xqds = new SaxonXQDataSource();
82-
String query = "for $user in doc(\"users.xml\")/Users/User[name='" + nameStr + "'] return $user/password";
88+
String query = "for $user in doc(\"users.xml\")/Users/User[name='" + nameStr
89+
+ "'] return $user/password";
8390
XQConnection conn = xqds.getConnection();
8491
XQExpression expr = conn.createExpression();
8592
XQResultSequence result = expr.executeQuery(query);
86-
while (result.next()){
93+
while (result.next()) {
8794
System.out.println(result.getItemAsString(null));
8895
}
8996
}
@@ -95,7 +102,7 @@ public void testInputStreambad(HttpServletRequest request) throws Exception {
95102
XQConnection conn = ds.getConnection();
96103
XQPreparedExpression xqpe = conn.prepareExpression(name);
97104
XQResultSequence result = xqpe.executeQuery();
98-
while (result.next()){
105+
while (result.next()) {
99106
System.out.println(result.getItemAsString(null));
100107
}
101108
}
@@ -107,7 +114,7 @@ public void testInputStreambad1(HttpServletRequest request) throws Exception {
107114
XQConnection conn = xqds.getConnection();
108115
XQExpression expr = conn.createExpression();
109116
XQResultSequence result = expr.executeQuery(name);
110-
while (result.next()){
117+
while (result.next()) {
111118
System.out.println(result.getItemAsString(null));
112119
}
113120
}
@@ -120,7 +127,7 @@ public void testReaderbad(HttpServletRequest request) throws Exception {
120127
XQConnection conn = ds.getConnection();
121128
XQPreparedExpression xqpe = conn.prepareExpression(br);
122129
XQResultSequence result = xqpe.executeQuery();
123-
while (result.next()){
130+
while (result.next()) {
124131
System.out.println(result.getItemAsString(null));
125132
}
126133
}
@@ -133,11 +140,26 @@ public void testReaderbad1(HttpServletRequest request) throws Exception {
133140
XQConnection conn = xqds.getConnection();
134141
XQExpression expr = conn.createExpression();
135142
XQResultSequence result = expr.executeQuery(br);
136-
while (result.next()){
143+
while (result.next()) {
137144
System.out.println(result.getItemAsString(null));
138145
}
139146
}
140147

148+
@RequestMapping
149+
public void testExecuteCommandbad(HttpServletRequest request) throws Exception {
150+
String name = request.getParameter("name");
151+
XQDataSource xqds = new SaxonXQDataSource();
152+
XQConnection conn = xqds.getConnection();
153+
XQExpression expr = conn.createExpression();
154+
//bad code
155+
expr.executeCommand(name);
156+
//bad code
157+
InputStream is = request.getInputStream();
158+
BufferedReader br = new BufferedReader(new InputStreamReader(is));
159+
expr.executeCommand(br);
160+
expr.close();
161+
}
162+
141163
@RequestMapping
142164
public void good(HttpServletRequest request) throws XQException {
143165
String name = request.getParameter("name");
@@ -146,9 +168,10 @@ public void good(HttpServletRequest request) throws XQException {
146168
String query = "declare variable $name as xs:string external;"
147169
+ " for $user in doc(\"users.xml\")/Users/User[name=$name] return $user/password";
148170
XQPreparedExpression xqpe = conn.prepareExpression(query);
149-
xqpe.bindString(new QName("name"), name, conn.createAtomicType(XQItemType.XQBASETYPE_STRING));
171+
xqpe.bindString(new QName("name"), name,
172+
conn.createAtomicType(XQItemType.XQBASETYPE_STRING));
150173
XQResultSequence result = xqpe.executeQuery();
151-
while (result.next()){
174+
while (result.next()) {
152175
System.out.println(result.getItemAsString(null));
153176
}
154177
}
@@ -161,10 +184,12 @@ public void good1(HttpServletRequest request) throws XQException {
161184
XQDataSource xqds = new SaxonXQDataSource();
162185
XQConnection conn = xqds.getConnection();
163186
XQExpression expr = conn.createExpression();
164-
expr.bindString(new QName("name"), name, conn.createAtomicType(XQItemType.XQBASETYPE_STRING));
187+
expr.bindString(new QName("name"), name,
188+
conn.createAtomicType(XQItemType.XQBASETYPE_STRING));
165189
XQResultSequence result = expr.executeQuery(query);
166-
while (result.next()){
190+
while (result.next()) {
167191
System.out.println(result.getItemAsString(null));
168192
}
169193
}
170-
}
194+
}
195+

java/ql/test/stubs/saxon-xqj-9.x/net/sf/saxon/xqj/SaxonXQConnection.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import javax.xml.xquery.XQConnection;
66
import javax.xml.xquery.XQPreparedExpression;
77
import javax.xml.xquery.XQException;
8+
import javax.xml.xquery.XQExpression;
89
import javax.xml.xquery.XQStaticContext;
910
import java.io.InputStream;
1011

0 commit comments

Comments
 (0)