Files
codeql/java/ql/lib/semmle/code/java/security/QueryInjection.qll
Ian Lynagh 6566f7b69f Kotlin: Add types for the different kinds of casts that Kotlin has
We might want to unify some of these in future, but doing that
correctly is easier than splitting them up correctly, so I've given each
one its own QL class for now.

I am not familiar with many of the libraries/queries that use CastExpr.
I've briefly looked at them and updated them in a way that looks
superficially reasonable, but some of the uses will probably want to be
refined later.
2022-05-10 19:51:13 +01:00

72 lines
2.7 KiB
Plaintext

/** Provides classes to reason about database query language injection vulnerabilities. */
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.frameworks.javaee.Persistence
private import semmle.code.java.frameworks.MyBatis
private import semmle.code.java.dataflow.ExternalFlow
/** A sink for database query language injection vulnerabilities. */
abstract class QueryInjectionSink extends DataFlow::Node { }
/**
* A unit class for adding additional taint steps.
*
* Extend this class to add additional taint steps that should apply to the SQL
* injection taint configuration.
*/
class AdditionalQueryInjectionTaintStep extends Unit {
/**
* Holds if the step from `node1` to `node2` should be considered a taint
* step for SQL injection taint configurations.
*/
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
}
/** A sink for SQL injection vulnerabilities. */
private class SqlInjectionSink extends QueryInjectionSink {
SqlInjectionSink() { sinkNode(this, "sql") }
}
/** A sink for Java Persistence Query Language injection vulnerabilities. */
private class PersistenceQueryInjectionSink extends QueryInjectionSink {
PersistenceQueryInjectionSink() {
// the query (first) argument to a `createQuery` or `createNativeQuery` method on `EntityManager`
exists(MethodAccess call, TypeEntityManager em | call.getArgument(0) = this.asExpr() |
call.getMethod() = em.getACreateQueryMethod() or
call.getMethod() = em.getACreateNativeQueryMethod()
// note: `createNamedQuery` is safe, as it takes only the query name,
// and named queries can only be constructed using constants as the query text
)
}
}
/** A sink for MongoDB injection vulnerabilities. */
private class MongoDbInjectionSink extends QueryInjectionSink {
MongoDbInjectionSink() {
exists(MethodAccess call |
call.getMethod().getDeclaringType().hasQualifiedName("com.mongodb", "BasicDBObject") and
call.getMethod().hasName("parse") and
this.asExpr() = call.getArgument(0)
)
or
exists(CastingExpr c |
c.getExpr() = this.asExpr() and
c.getTypeExpr().getType().(RefType).hasQualifiedName("com.mongodb", "DBObject")
)
}
}
private class MongoJsonStep extends AdditionalQueryInjectionTaintStep {
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma |
ma.getMethod().getDeclaringType().hasQualifiedName("com.mongodb.util", "JSON") and
ma.getMethod().hasName("parse") and
ma.getArgument(0) = node1.asExpr() and
ma = node2.asExpr()
)
}
}
private class MyBatisSqlInjectionSink extends QueryInjectionSink instanceof MyBatisInjectionSink { }