mirror of
https://github.com/github/codeql.git
synced 2026-04-29 02:35:15 +02:00
*)add CWE-652 XQueryInjection detection
This commit is contained in:
35
java/ql/src/Security/CWE/CWE-652/XQueryInjection.java
Normal file
35
java/ql/src/Security/CWE/CWE-652/XQueryInjection.java
Normal 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));
|
||||
}
|
||||
}
|
||||
34
java/ql/src/Security/CWE/CWE-652/XQueryInjection.qhelp
Normal file
34
java/ql/src/Security/CWE/CWE-652/XQueryInjection.qhelp
Normal 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>
|
||||
21
java/ql/src/Security/CWE/CWE-652/XQueryInjection.ql
Normal file
21
java/ql/src/Security/CWE/CWE-652/XQueryInjection.ql
Normal 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"
|
||||
35
java/ql/src/Security/CWE/CWE-652/XQueryInjectionLib.qll
Normal file
35
java/ql/src/Security/CWE/CWE-652/XQueryInjectionLib.qll
Normal 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)
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user