Skip to content

Commit 0b326aa

Browse files
authored
*)update XQueryInjectionLib.qll
1 parent 44d99f8 commit 0b326aa

File tree

1 file changed

+74
-19
lines changed

1 file changed

+74
-19
lines changed
Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,90 @@
11
import java
22
import semmle.code.java.dataflow.FlowSources
3+
import semmle.code.java.dataflow.TaintTracking2
4+
import DataFlow::PathGraph
35

4-
class XQueryInjectionConfig extends TaintTracking::Configuration {
5-
XQueryInjectionConfig() { this = "XQueryInjectionConfig" }
6+
/** A call to `XQConnection.prepareExpression`. */
7+
class XQueryParserCall extends MethodAccess {
8+
XQueryParserCall() {
9+
exists(Method m |
10+
this.getMethod() = m and
11+
m.getDeclaringType()
12+
.getASourceSupertype*()
13+
.hasQualifiedName("javax.xml.xquery", "XQConnection") and
14+
m.hasName("prepareExpression")
15+
)
16+
}
17+
// return the first parameter of the `bindString` method and use it as a sink
18+
Expr getSink() { result = this.getArgument(0) }
19+
}
20+
21+
/** A call to `XQDynamicContext.bindString`. */
22+
class XQueryBindStringCall extends MethodAccess {
23+
XQueryBindStringCall() {
24+
exists(Method m |
25+
this.getMethod() = m and
26+
m.getDeclaringType()
27+
.getASourceSupertype*()
28+
.hasQualifiedName("javax.xml.xquery", "XQDynamicContext") and
29+
m.hasName("bindString")
30+
)
31+
}
32+
// return the second parameter of the `bindString` method and use it as a sink
33+
Expr getSink() { result = this.getArgument(1) }
34+
}
35+
36+
/** Used to determine whether to call the `prepareExpression` method, and the first parameter value can be remotely controlled. */
37+
class ParserParameterRemoteFlowConf extends TaintTracking2::Configuration {
38+
ParserParameterRemoteFlowConf() { this = "ParserParameterRemoteFlowConf" }
639

7-
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
40+
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
841

9-
override predicate isSink(DataFlow::Node sink) { sink instanceof XQueryInjectionSink }
42+
override predicate isSink(DataFlow::Node sink) {
43+
exists(XQueryParserCall xqpc | xqpc.getSink() = sink.asExpr())
44+
}
1045
}
1146

12-
/*Find if the executeQuery method is finally called.*/
13-
predicate executeQuery(MethodAccess ma) {
14-
exists(LocalVariableDeclExpr lvd, MethodAccess ma1, Method m | lvd.getAChildExpr() = ma |
15-
m = ma1.getMethod() and
16-
m.hasName("executeQuery") and
17-
m.getDeclaringType()
18-
.getASourceSupertype*()
19-
.hasQualifiedName("javax.xml.xquery", "XQPreparedExpression") and
20-
ma1.getQualifier() = lvd.getAnAccess()
21-
)
47+
/** Used to determine whether to call the `bindString` method, and the second parameter value can be controlled remotely. */
48+
class BindParameterRemoteFlowConf extends TaintTracking2::Configuration {
49+
BindParameterRemoteFlowConf() { this = "BindParameterRemoteFlowConf" }
50+
51+
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
52+
53+
override predicate isSink(DataFlow::Node sink) {
54+
exists(XQueryBindStringCall xqbsc | xqbsc.getSink() = sink.asExpr())
55+
}
2256
}
2357

24-
class XQueryInjectionSink extends DataFlow::ExprNode {
25-
XQueryInjectionSink() {
26-
exists(MethodAccess ma, Method m | m = ma.getMethod() |
58+
/**
59+
* A data flow source for XQuery injection vulnerability.
60+
* 1. `prepareExpression` call as sink.
61+
* 2. Determine whether the `var1` parameter of `prepareExpression` method can be controlled remotely.
62+
*/
63+
class XQueryInjectionSource extends DataFlow::ExprNode {
64+
XQueryInjectionSource() {
65+
exists(MethodAccess ma, Method m, ParserParameterRemoteFlowConf conf, DataFlow::Node node |
66+
m = ma.getMethod()
67+
|
2768
m.hasName("prepareExpression") and
2869
m.getDeclaringType()
2970
.getASourceSupertype*()
3071
.hasQualifiedName("javax.xml.xquery", "XQConnection") and
31-
executeQuery(ma) and
32-
asExpr() = ma.getArgument(0)
72+
asExpr() = ma and
73+
node.asExpr() = ma.getArgument(0) and
74+
conf.hasFlowTo(node)
75+
)
76+
}
77+
}
78+
79+
/** A data flow sink for XQuery injection vulnerability. */
80+
class XQueryInjectionSink extends DataFlow::Node {
81+
XQueryInjectionSink() {
82+
exists(MethodAccess ma, Method m | m = ma.getMethod() |
83+
m.hasName("executeQuery") and
84+
m.getDeclaringType()
85+
.getASourceSupertype*()
86+
.hasQualifiedName("javax.xml.xquery", "XQPreparedExpression") and
87+
asExpr() = ma.getQualifier()
3388
)
3489
}
3590
}

0 commit comments

Comments
 (0)