*)update XQueryInjectionLib.qll

This commit is contained in:
haby0
2021-01-23 18:27:38 +08:00
committed by GitHub
parent 44d99f8cd4
commit 0b326aae20

View File

@@ -1,35 +1,90 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking2
import DataFlow::PathGraph
class XQueryInjectionConfig extends TaintTracking::Configuration {
XQueryInjectionConfig() { this = "XQueryInjectionConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof XQueryInjectionSink }
/** A call to `XQConnection.prepareExpression`. */
class XQueryParserCall extends MethodAccess {
XQueryParserCall() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName("javax.xml.xquery", "XQConnection") and
m.hasName("prepareExpression")
)
}
// return the first parameter of the `bindString` method and use it as a sink
Expr getSink() { result = this.getArgument(0) }
}
/*Find if the executeQuery method is finally called.*/
predicate executeQuery(MethodAccess ma) {
exists(LocalVariableDeclExpr lvd, MethodAccess ma1, Method m | lvd.getAChildExpr() = ma |
m = ma1.getMethod() and
m.hasName("executeQuery") and
m.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName("javax.xml.xquery", "XQPreparedExpression") and
ma1.getQualifier() = lvd.getAnAccess()
)
/** A call to `XQDynamicContext.bindString`. */
class XQueryBindStringCall extends MethodAccess {
XQueryBindStringCall() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName("javax.xml.xquery", "XQDynamicContext") and
m.hasName("bindString")
)
}
// return the second parameter of the `bindString` method and use it as a sink
Expr getSink() { result = this.getArgument(1) }
}
class XQueryInjectionSink extends DataFlow::ExprNode {
XQueryInjectionSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
/** Used to determine whether to call the `prepareExpression` method, and the first parameter value can be remotely controlled. */
class ParserParameterRemoteFlowConf extends TaintTracking2::Configuration {
ParserParameterRemoteFlowConf() { this = "ParserParameterRemoteFlowConf" }
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
exists(XQueryParserCall xqpc | xqpc.getSink() = sink.asExpr())
}
}
/** Used to determine whether to call the `bindString` method, and the second parameter value can be controlled remotely. */
class BindParameterRemoteFlowConf extends TaintTracking2::Configuration {
BindParameterRemoteFlowConf() { this = "BindParameterRemoteFlowConf" }
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
exists(XQueryBindStringCall xqbsc | xqbsc.getSink() = sink.asExpr())
}
}
/**
* A data flow source for XQuery injection vulnerability.
* 1. `prepareExpression` call as sink.
* 2. Determine whether the `var1` parameter of `prepareExpression` method can be controlled remotely.
*/
class XQueryInjectionSource extends DataFlow::ExprNode {
XQueryInjectionSource() {
exists(MethodAccess ma, Method m, ParserParameterRemoteFlowConf conf, DataFlow::Node node |
m = ma.getMethod()
|
m.hasName("prepareExpression") and
m.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName("javax.xml.xquery", "XQConnection") and
executeQuery(ma) and
asExpr() = ma.getArgument(0)
asExpr() = ma and
node.asExpr() = ma.getArgument(0) and
conf.hasFlowTo(node)
)
}
}
/** A data flow sink for XQuery injection vulnerability. */
class XQueryInjectionSink extends DataFlow::Node {
XQueryInjectionSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
m.hasName("executeQuery") and
m.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName("javax.xml.xquery", "XQPreparedExpression") and
asExpr() = ma.getQualifier()
)
}
}