Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 2 additions & 44 deletions java/ql/src/Security/CWE/CWE-089/SqlInjectionLib.qll
Original file line number Diff line number Diff line change
@@ -1,50 +1,8 @@
/** Definitions used by the queries for database query injection. */

import semmle.code.java.Expr
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.frameworks.android.SQLite
import semmle.code.java.frameworks.javaee.Persistence
import semmle.code.java.frameworks.SpringJdbc
import semmle.code.java.frameworks.MyBatis
import semmle.code.java.frameworks.Hibernate

/** A sink for database query language injection vulnerabilities. */
abstract class QueryInjectionSink extends DataFlow::ExprNode { }

/** A sink for SQL injection vulnerabilities. */
class SqlInjectionSink extends QueryInjectionSink {
SqlInjectionSink() {
this.getExpr() instanceof SqlExpr
or
exists(MethodAccess ma, Method m, int index |
ma.getMethod() = m and
ma.getArgument(index) = this.getExpr()
|
index = m.(SQLiteRunner).sqlIndex()
or
m instanceof BatchUpdateVarargsMethod
or
index = 0 and jdbcSqlMethod(m)
or
index = 0 and mybatisSqlMethod(m)
or
index = 0 and hibernateSqlMethod(m)
)
}
}

/** A sink for Java Persistence Query Language injection vulnerabilities. */
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.getExpr() |
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
)
}
}
import semmle.code.java.security.QueryInjection

private class QueryInjectionFlowConfig extends TaintTracking::Configuration {
QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }
Expand Down
2 changes: 1 addition & 1 deletion java/ql/src/Security/CWE/CWE-089/SqlUnescaped.ql
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class UncontrolledStringBuilderSourceFlowConfig extends TaintTracking::Configura
from QueryInjectionSink query, Expr uncontrolled
where
(
builtFromUncontrolledConcat(query.getExpr(), uncontrolled)
builtFromUncontrolledConcat(query.asExpr(), uncontrolled)
or
exists(StringBuilderVar sbv, UncontrolledStringBuilderSourceFlowConfig conf |
uncontrolledStringBuilderQuery(sbv, uncontrolled) and
Expand Down
48 changes: 48 additions & 0 deletions java/ql/src/semmle/code/java/security/QueryInjection.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/** Provides classes to reason about database query language injection vulnerabilities. */

import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.frameworks.Jdbc
import semmle.code.java.frameworks.android.SQLite
import semmle.code.java.frameworks.javaee.Persistence
import semmle.code.java.frameworks.SpringJdbc
import semmle.code.java.frameworks.MyBatis
import semmle.code.java.frameworks.Hibernate

/** A sink for database query language injection vulnerabilities. */
abstract class QueryInjectionSink extends DataFlow::Node { }

/** A sink for SQL injection vulnerabilities. */
private class SqlInjectionSink extends QueryInjectionSink {
SqlInjectionSink() {
this.asExpr() instanceof SqlExpr
or
exists(MethodAccess ma, Method m, int index |
ma.getMethod() = m and
ma.getArgument(index) = this.asExpr()
|
index = m.(SQLiteRunner).sqlIndex()
or
m instanceof BatchUpdateVarargsMethod
or
index = 0 and jdbcSqlMethod(m)
or
index = 0 and mybatisSqlMethod(m)
or
index = 0 and hibernateSqlMethod(m)
)
}
}

/** 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
)
}
}