*)add CWE-652 XQueryInjection detection

This commit is contained in:
haby0
2021-01-21 19:18:10 +08:00
parent 9cfbe6feb7
commit a56dd60baa
4 changed files with 125 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
import javax.servlet.http.HttpServletRequest;
import javax.xml.namespace.QName;
import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQDataSource;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQItemType;
import javax.xml.xquery.XQPreparedExpression;
import javax.xml.xquery.XQResultSequence;
import net.sf.saxon.xqj.SaxonXQDataSource;
public void bad(HttpServletRequest request) throws XQException {
String name = request.getParameter("name");
XQDataSource ds = new SaxonXQDataSource();
XQConnection conn = ds.getConnection();
String query = "for $user in doc(\"users.xml\")/Users/User[name='" + name + "'] return $user/password";
XQPreparedExpression xqpe = conn.prepareExpression(query);
XQResultSequence result = xqpe.executeQuery();
while (result.next()){
System.out.println(result.getItemAsString(null));
}
}
public void good(HttpServletRequest request) throws XQException {
String name = request.getParameter("name");
XQDataSource ds = new SaxonXQDataSource();
XQConnection conn = ds.getConnection();
String query = "declare variable $name as xs:string external;"
+ " for $user in doc(\"users.xml\")/Users/User[name=$name] return $user/password";
XQPreparedExpression xqpe = conn.prepareExpression(query);
xqpe.bindString(new QName("name"), name, conn.createAtomicType(XQItemType.XQBASETYPE_STRING));
XQResultSequence result = xqpe.executeQuery();
while (result.next()){
System.out.println(result.getItemAsString(null));
}
}

View File

@@ -0,0 +1,34 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The software uses external input to dynamically construct an XQuery expression used to retrieve data from an XML database, but it does not neutralize or incorrectly neutralizes that input.
This allows an attacker to control the structure of the query.</p>
</overview>
<recommendation>
<p>Use parameterized queries. This will help ensure separation between data plane and control plane.</p>
</recommendation>
<example>
<p>This example is a comparison of unused parameterized query and using parameterized query.
Parameterized query through <code>bindString</code>.</p>
<sample src="XQueryInjection.java" />
</example>
<references>
<li>cwe description:
<a href="https://cwe.mitre.org/data/definitions/652.html">XQuery Injection</a>.</li>
<!-- LocalWords: CWE
-->
</references>
</qhelp>

View File

@@ -0,0 +1,21 @@
/**
* @name XQuery query built from user-controlled sources
* @description Building an XQuery query from user-controlled sources is vulnerable to insertion of
* malicious XQuery code by the user.
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/XQuery-injection
* @tags security
* external/cwe/cwe-652
*/
import java
import semmle.code.java.dataflow.FlowSources
import XQueryInjectionLib
import DataFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, XQueryInjectionConfig conf
where conf.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "XQuery query might include code from $@.", source.getNode(),
"this user input"

View File

@@ -0,0 +1,35 @@
import java
import semmle.code.java.dataflow.FlowSources
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 }
}
/*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()
)
}
class XQueryInjectionSink extends DataFlow::ExprNode {
XQueryInjectionSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
m.hasName("prepareExpression") and
m.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName("javax.xml.xquery", "XQConnection") and
executeQuery(ma) and
asExpr() = ma.getArgument(0)
)
}
}