mirror of
https://github.com/github/codeql.git
synced 2025-12-21 11:16:30 +01:00
Merge pull request #5487 from joefarebrother/sql-sinks
Java: Convert SQL sinks to CSV format
This commit is contained in:
@@ -95,6 +95,12 @@ private module Frameworks {
|
||||
private import semmle.code.java.security.LdapInjection
|
||||
private import semmle.code.java.security.XPath
|
||||
private import semmle.code.java.security.JexlInjection
|
||||
private import semmle.code.java.frameworks.android.SQLite
|
||||
private import semmle.code.java.frameworks.Jdbc
|
||||
private import semmle.code.java.frameworks.SpringJdbc
|
||||
private import semmle.code.java.frameworks.MyBatis
|
||||
private import semmle.code.java.frameworks.Hibernate
|
||||
private import semmle.code.java.frameworks.jOOQ
|
||||
}
|
||||
|
||||
private predicate sourceModelCsv(string row) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/** The interface `org.hibernate.query.QueryProducer`. */
|
||||
class HibernateQueryProducer extends RefType {
|
||||
@@ -21,19 +22,18 @@ class HibernateSession extends RefType {
|
||||
HibernateSession() { this.hasQualifiedName("org.hibernate", "Session") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `m` is a method on `HibernateQueryProducer`, or `HibernateSharedSessionContract`
|
||||
* or `HibernateSession`, or a subclass, taking an SQL string as its first argument.
|
||||
*/
|
||||
predicate hibernateSqlMethod(Method m) {
|
||||
exists(RefType t |
|
||||
t = m.getDeclaringType().getASourceSupertype*() and
|
||||
(
|
||||
t instanceof HibernateQueryProducer or
|
||||
t instanceof HibernateSharedSessionContract or
|
||||
t instanceof HibernateSession
|
||||
)
|
||||
) and
|
||||
m.getParameterType(0) instanceof TypeString and
|
||||
m.hasName(["createQuery", "createNativeQuery", "createSQLQuery"])
|
||||
private class SqlSinkCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
//"package;type;overrides;name;signature;ext;spec;kind"
|
||||
"org.hibernate;QueryProducer;true;createQuery;;;Argument[0];sql",
|
||||
"org.hibernate;QueryProducer;true;createNativeQuery;;;Argument[0];sql",
|
||||
"org.hibernate;QueryProducer;true;createSQLQuery;;;Argument[0];sql",
|
||||
"org.hibernate;SharedSessionContract;true;createQuery;;;Argument[0];sql",
|
||||
"org.hibernate;SharedSessionContract;true;createSQLQuery;;;Argument[0];sql",
|
||||
"org.hibernate;Session;true;createQuery;;;Argument[0];sql",
|
||||
"org.hibernate;Session;true;createSQLQuery;;;Argument[0];sql"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import semmle.code.java.Type
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/*--- Types ---*/
|
||||
/** The interface `java.sql.Connection`. */
|
||||
@@ -26,62 +27,6 @@ class TypeStatement extends Interface {
|
||||
}
|
||||
|
||||
/*--- Methods ---*/
|
||||
/** A method with the name `prepareStatement` declared in `java.sql.Connection`. */
|
||||
class ConnectionPrepareStatement extends Method {
|
||||
ConnectionPrepareStatement() {
|
||||
getDeclaringType() instanceof TypeConnection and
|
||||
hasName("prepareStatement")
|
||||
}
|
||||
}
|
||||
|
||||
/** A method with the name `prepareCall` declared in `java.sql.Connection`. */
|
||||
class ConnectionPrepareCall extends Method {
|
||||
ConnectionPrepareCall() {
|
||||
getDeclaringType() instanceof TypeConnection and
|
||||
hasName("prepareCall")
|
||||
}
|
||||
}
|
||||
|
||||
/** A method with the name `executeQuery` declared in `java.sql.Statement`. */
|
||||
class StatementExecuteQuery extends Method {
|
||||
StatementExecuteQuery() {
|
||||
getDeclaringType() instanceof TypeStatement and
|
||||
hasName("executeQuery")
|
||||
}
|
||||
}
|
||||
|
||||
/** A method with the name `execute` declared in `java.sql.Statement`. */
|
||||
class MethodStatementExecute extends Method {
|
||||
MethodStatementExecute() {
|
||||
getDeclaringType() instanceof TypeStatement and
|
||||
hasName("execute")
|
||||
}
|
||||
}
|
||||
|
||||
/** A method with the name `executeUpdate` declared in `java.sql.Statement`. */
|
||||
class MethodStatementExecuteUpdate extends Method {
|
||||
MethodStatementExecuteUpdate() {
|
||||
getDeclaringType() instanceof TypeStatement and
|
||||
hasName("executeUpdate")
|
||||
}
|
||||
}
|
||||
|
||||
/** A method with the name `executeLargeUpdate` declared in `java.sql.Statement`. */
|
||||
class MethodStatementExecuteLargeUpdate extends Method {
|
||||
MethodStatementExecuteLargeUpdate() {
|
||||
getDeclaringType() instanceof TypeStatement and
|
||||
hasName("executeLargeUpdate")
|
||||
}
|
||||
}
|
||||
|
||||
/** A method with the name `addBatch` declared in `java.sql.Statement`. */
|
||||
class MethodStatementAddBatch extends Method {
|
||||
MethodStatementAddBatch() {
|
||||
getDeclaringType() instanceof TypeStatement and
|
||||
hasName("addBatch")
|
||||
}
|
||||
}
|
||||
|
||||
/** A method with the name `getString` declared in `java.sql.ResultSet`. */
|
||||
class ResultSetGetStringMethod extends Method {
|
||||
ResultSetGetStringMethod() {
|
||||
@@ -92,24 +37,18 @@ class ResultSetGetStringMethod extends Method {
|
||||
}
|
||||
|
||||
/*--- Other definitions ---*/
|
||||
/**
|
||||
* An expression representing SQL code that occurs as an argument of
|
||||
* a method in `java.sql.Connection` or `java.sql.Statement`.
|
||||
*/
|
||||
class SqlExpr extends Expr {
|
||||
SqlExpr() {
|
||||
exists(MethodAccess call, Method method |
|
||||
call.getArgument(0) = this and
|
||||
method = call.getMethod() and
|
||||
(
|
||||
method instanceof ConnectionPrepareStatement or
|
||||
method instanceof ConnectionPrepareCall or
|
||||
method instanceof StatementExecuteQuery or
|
||||
method instanceof MethodStatementExecute or
|
||||
method instanceof MethodStatementExecuteUpdate or
|
||||
method instanceof MethodStatementExecuteLargeUpdate or
|
||||
method instanceof MethodStatementAddBatch
|
||||
)
|
||||
)
|
||||
private class SqlSinkCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
//"package;type;overrides;name;signature;ext;spec;kind"
|
||||
"java.sql;Connection;true;prepareStatement;;;Argument[0];sql",
|
||||
"java.sql;Connection;true;prepareCall;;;Argument[0];sql",
|
||||
"java.sql;Statement;true;execute;;;Argument[0];sql",
|
||||
"java.sql;Statement;true;executeQuery;;;Argument[0];sql",
|
||||
"java.sql;Statement;true;executeUpdate;;;Argument[0];sql",
|
||||
"java.sql;Statement;true;executeLargeUpdate;;;Argument[0];sql",
|
||||
"java.sql;Statement;true;addBatch;;;Argument[0];sql"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,25 +3,24 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/** The class `org.apache.ibatis.jdbc.SqlRunner`. */
|
||||
class MyBatisSqlRunner extends RefType {
|
||||
MyBatisSqlRunner() { this.hasQualifiedName("org.apache.ibatis.jdbc", "SqlRunner") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `m` is a method on `MyBatisSqlRunner` taking an SQL string as its
|
||||
* first argument.
|
||||
*/
|
||||
predicate mybatisSqlMethod(Method m) {
|
||||
m.getDeclaringType() instanceof MyBatisSqlRunner and
|
||||
m.getParameterType(0) instanceof TypeString and
|
||||
(
|
||||
m.hasName("delete") or
|
||||
m.hasName("insert") or
|
||||
m.hasName("run") or
|
||||
m.hasName("selectAll") or
|
||||
m.hasName("selectOne") or
|
||||
m.hasName("update")
|
||||
)
|
||||
private class SqlSinkCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
//"package;type;overrides;name;signature;ext;spec;kind"
|
||||
"org.apache.ibatis.jdbc;SqlRunner;false;delete;(String,Object[]);;Argument[0];sql",
|
||||
"org.apache.ibatis.jdbc;SqlRunner;false;insert;(String,Object[]);;Argument[0];sql",
|
||||
"org.apache.ibatis.jdbc;SqlRunner;false;run;(String);;Argument[0];sql",
|
||||
"org.apache.ibatis.jdbc;SqlRunner;false;selectAll;(String,Object[]);;Argument[0];sql",
|
||||
"org.apache.ibatis.jdbc;SqlRunner;false;selectOne;(String,Object[]);;Argument[0];sql",
|
||||
"org.apache.ibatis.jdbc;SqlRunner;false;update;(String,Object[]);;Argument[0];sql"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,33 +3,28 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/** The class `org.springframework.jdbc.core.JdbcTemplate`. */
|
||||
class JdbcTemplate extends RefType {
|
||||
JdbcTemplate() { this.hasQualifiedName("org.springframework.jdbc.core", "JdbcTemplate") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `m` is a method on `JdbcTemplate` taking an SQL string as its first
|
||||
* argument.
|
||||
*/
|
||||
predicate jdbcSqlMethod(Method m) {
|
||||
m.getDeclaringType() instanceof JdbcTemplate and
|
||||
m.getParameterType(0) instanceof TypeString and
|
||||
(
|
||||
m.hasName("batchUpdate") or
|
||||
m.hasName("execute") or
|
||||
m.getName().matches("query%") or
|
||||
m.hasName("update")
|
||||
)
|
||||
}
|
||||
|
||||
/** The method `JdbcTemplate.batchUpdate(String... sql)` */
|
||||
class BatchUpdateVarargsMethod extends Method {
|
||||
BatchUpdateVarargsMethod() {
|
||||
this.getDeclaringType() instanceof JdbcTemplate and
|
||||
this.hasName("batchUpdate") and
|
||||
this.getParameterType(0).(Array).getComponentType() instanceof TypeString and
|
||||
this.getParameter(0).isVarargs()
|
||||
private class SqlSinkCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
//"package;type;overrides;name;signature;ext;spec;kind"
|
||||
"org.springframework.jdbc.core;JdbcTemplate;false;batchUpdate;(String[]);;Argument[0];sql",
|
||||
"org.springframework.jdbc.core;JdbcTemplate;false;batchUpdate;;;Argument[0];sql",
|
||||
"org.springframework.jdbc.core;JdbcTemplate;false;execute;;;Argument[0];sql",
|
||||
"org.springframework.jdbc.core;JdbcTemplate;false;update;;;Argument[0];sql",
|
||||
"org.springframework.jdbc.core;JdbcTemplate;false;query;;;Argument[0];sql",
|
||||
"org.springframework.jdbc.core;JdbcTemplate;false;queryForList;;;Argument[0];sql",
|
||||
"org.springframework.jdbc.core;JdbcTemplate;false;queryForMap;;;Argument[0];sql",
|
||||
"org.springframework.jdbc.core;JdbcTemplate;false;queryForObject;;;Argument[0];sql",
|
||||
"org.springframework.jdbc.core;JdbcTemplate;false;queryForRowSet;;;Argument[0];sql",
|
||||
"org.springframework.jdbc.core;JdbcTemplate;false;queryForStream;;;Argument[0];sql"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import java
|
||||
import Android
|
||||
import semmle.code.java.dataflow.FlowSteps
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* The class `android.database.sqlite.SQLiteDatabase`.
|
||||
@@ -23,209 +24,90 @@ class TypeDatabaseUtils extends Class {
|
||||
TypeDatabaseUtils() { hasQualifiedName("android.database", "DatabaseUtils") }
|
||||
}
|
||||
|
||||
abstract class SQLiteRunner extends Method {
|
||||
abstract int sqlIndex();
|
||||
}
|
||||
|
||||
private class ExecSqlMethod extends SQLiteRunner {
|
||||
ExecSqlMethod() {
|
||||
this.getDeclaringType() instanceof TypeSQLiteDatabase and
|
||||
// execPerConnectionSQL(String sql, Object[] bindArgs)
|
||||
// execSQL(String sql)
|
||||
// execSQL(String sql, Object[] bindArgs)
|
||||
this.hasName(["execPerConnectionSQL", "execSQL"])
|
||||
private class SQLiteSinkCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
//"package;type;overrides;name;signature;ext;spec;kind"
|
||||
"android.database.sqlite;SQLiteDatabase;false;compileStatement;(String);;Argument[0];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;execSQL;(String);;Argument[0];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;execSQL;(String,Object[]);;Argument[0];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;execPerConnectionSQL;(String,Object[]);;Argument[0];sql",
|
||||
// query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
|
||||
// query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)
|
||||
// query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
|
||||
// query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
|
||||
// queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)
|
||||
// queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
|
||||
// Each String / String[] arg except for selectionArgs is a sink
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(String,String[],String,String[],String,String,String,String);;Argument[0];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(String,String[],String,String[],String,String,String,String);;Argument[1];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(String,String[],String,String[],String,String,String,String);;Argument[2];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(String,String[],String,String[],String,String,String,String);;Argument[4..7];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(String,String[],String,String[],String,String,String);;Argument[0..2];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(String,String[],String,String[],String,String,String);;Argument[4..6];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(boolean,String,String[],String,String[],String,String,String,String);;Argument[1];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(boolean,String,String[],String,String[],String,String,String,String);;Argument[2];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(boolean,String,String[],String,String[],String,String,String,String);;Argument[3];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(boolean,String,String[],String,String[],String,String,String,String);;Argument[5..8];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(boolean,String,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[1];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(boolean,String,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[2];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(boolean,String,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[3];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;query;(boolean,String,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[5..8];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;queryWithFactory;(CursorFactory,boolean,String,String[],String,String[],String,String,String,String);;Argument[2];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;queryWithFactory;(CursorFactory,boolean,String,String[],String,String[],String,String,String,String);;Argument[3];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;queryWithFactory;(CursorFactory,boolean,String,String[],String,String[],String,String,String,String);;Argument[4];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;queryWithFactory;(CursorFactory,boolean,String,String[],String,String[],String,String,String,String);;Argument[6..9];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;queryWithFactory;(CursorFactory,boolean,String,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[2];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;queryWithFactory;(CursorFactory,boolean,String,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[3];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;queryWithFactory;(CursorFactory,boolean,String,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[4];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;queryWithFactory;(CursorFactory,boolean,String,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[6..9];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;rawQuery;(String,String[]);;Argument[0];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;rawQuery;(String,String[],CancellationSignal);;Argument[0];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;rawQueryWithFactory;(CursorFactory,String,String[],String);;Argument[1];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;rawQueryWithFactory;(CursorFactory,String,String[],String,CancellationSignal);;Argument[1];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;delete;(String,String,String[]);;Argument[0..1];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;update;(String,ContentValues,String,String[]);;Argument[0];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;update;(String,ContentValues,String,String[]);;Argument[2];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;updateWithOnConflict;(String,ContentValues,String,String[],int);;Argument[0];sql",
|
||||
"android.database.sqlite;SQLiteDatabase;false;updateWithOnConflict;(String,ContentValues,String,String[],int);;Argument[2];sql",
|
||||
"android.database;DatabaseUtils;false;longForQuery;(SQLiteDatabase,String,String[]);;Argument[1];sql",
|
||||
"android.database;DatabaseUtils;false;stringForQuery;(SQLiteDatabase,String,String[]);;Argument[1];sql",
|
||||
"android.database;DatabaseUtils;false;blobFileDescriptorForQuery;(SQLiteDatabase,String,String[]);;Argument[1];sql",
|
||||
"android.database;DatabaseUtils;false;createDbFromSqlStatements;(Context,String,int,String);;Argument[3];sql",
|
||||
"android.database;DatabaseUtils;false;queryNumEntries;(SQLiteDatabase,String);;Argument[1];sql",
|
||||
"android.database;DatabaseUtils;false;queryNumEntries;(SQLiteDatabase,String,String);;Argument[1..2];sql",
|
||||
"android.database;DatabaseUtils;false;queryNumEntries;(SQLiteDatabase,String,String,String[]);;Argument[1..2];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;delete;(SQLiteDatabase,String,String[]);;Argument[-1];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;delete;(SQLiteDatabase,String,String[]);;Argument[1];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;insert;(SQLiteDatabase,ContentValues);;Argument[-1];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;update;(SQLiteDatabase,ContentValues,String,String[]);;Argument[-1];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;update;(SQLiteDatabase,ContentValues,String,String[]);;Argument[2];sql",
|
||||
// query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder)
|
||||
// query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit)
|
||||
// query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit, CancellationSignal cancellationSignal)
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String);;Argument[-1];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String);;Argument[1];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String);;Argument[2];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String);;Argument[4..6];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String,String);;Argument[-1];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String,String);;Argument[1];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String,String);;Argument[2];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String,String);;Argument[4..7];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[-1];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[1];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[2];sql",
|
||||
"android.database.sqlite;SQLiteQueryBuilder;true;query;(SQLiteDatabase,String[],String,String[],String,String,String,String,CancellationSignal);;Argument[4..7];sql",
|
||||
"android.content;ContentProvider;true;delete;(Uri,String,String[]);;Argument[1];sql",
|
||||
"android.content;ContentProvider;true;update;(Uri,ContentValues,String,String[]);;Argument[2];sql",
|
||||
"android.content;ContentProvider;true;query;(Uri,String[],String,String[],String,CancellationSignal);;Argument[2];sql",
|
||||
"android.content;ContentProvider;true;query;(Uri,String[],String,String[],String);;Argument[2];sql",
|
||||
"android.content;ContentResolver;true;delete;(Uri,String,String[]);;Argument[1];sql",
|
||||
"android.content;ContentResolver;true;update;(Uri,ContentValues,String,String[]);;Argument[2];sql",
|
||||
"android.content;ContentResolver;true;query;(Uri,String[],String,String[],String,CancellationSignal);;Argument[2];sql",
|
||||
"android.content;ContentResolver;true;query;(Uri,String[],String,String[],String);;Argument[2];sql"
|
||||
]
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = 0 }
|
||||
}
|
||||
|
||||
private class QueryMethod extends SQLiteRunner {
|
||||
QueryMethod() {
|
||||
this.getDeclaringType() instanceof TypeSQLiteDatabase and
|
||||
this.hasName(["query", "queryWithFactory"])
|
||||
}
|
||||
|
||||
override int sqlIndex() {
|
||||
// query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
|
||||
// query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)
|
||||
// query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
|
||||
// query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
|
||||
this.getName() = "query" and
|
||||
(
|
||||
if this.getParameter(0).getType() instanceof TypeString
|
||||
then result = [0, 1, 2, 4, 5, 6, 7]
|
||||
else result = [1, 2, 3, 5, 6, 7, 8]
|
||||
)
|
||||
or
|
||||
// queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)
|
||||
// queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
|
||||
this.getName() = "queryWithFactory" and result = [2, 3, 4, 6, 7, 8, 9]
|
||||
}
|
||||
}
|
||||
|
||||
private class RawQueryMethod extends SQLiteRunner {
|
||||
RawQueryMethod() {
|
||||
this.getDeclaringType() instanceof TypeSQLiteDatabase and
|
||||
this.hasName(["rawQuery", "rawQueryWithFactory"])
|
||||
}
|
||||
|
||||
override int sqlIndex() {
|
||||
// rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal)
|
||||
// rawQuery(String sql, String[] selectionArgs)
|
||||
this.getName() = "rawQuery" and result = 0
|
||||
or
|
||||
// rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable, CancellationSignal cancellationSignal)
|
||||
// rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable)
|
||||
this.getName() = "rawQueryWithFactory" and result = 1
|
||||
}
|
||||
}
|
||||
|
||||
private class CompileStatementMethod extends SQLiteRunner {
|
||||
CompileStatementMethod() {
|
||||
this.getDeclaringType() instanceof TypeSQLiteDatabase and
|
||||
// compileStatement(String sql)
|
||||
this.hasName("compileStatement")
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = 0 }
|
||||
}
|
||||
|
||||
private class DeleteMethod extends SQLiteRunner {
|
||||
DeleteMethod() {
|
||||
this.getDeclaringType() instanceof TypeSQLiteDatabase and
|
||||
// delete(String table, String whereClause, String[] whereArgs)
|
||||
this.hasName("delete")
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = 1 }
|
||||
}
|
||||
|
||||
private class UpdateMethod extends SQLiteRunner {
|
||||
UpdateMethod() {
|
||||
this.getDeclaringType() instanceof TypeSQLiteDatabase and
|
||||
// update(String table, ContentValues values, String whereClause, String[] whereArgs)
|
||||
// updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm)
|
||||
this.hasName(["update", "updateWithOnConflict"])
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = 2 }
|
||||
}
|
||||
|
||||
private class ForQueryMethod extends SQLiteRunner {
|
||||
ForQueryMethod() {
|
||||
// (blobFileDescriptor|long|string)ForQuery(SQLiteDatabase db, String query, String[] selectionArgs)
|
||||
this.getDeclaringType() instanceof TypeDatabaseUtils and
|
||||
this.hasName(["blobFileDescriptorForQuery", "longForQuery", "stringForQuery"]) and
|
||||
this.getNumberOfParameters() = 3
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = 1 }
|
||||
}
|
||||
|
||||
private class CreateDbFromSqlStatementsMethod extends SQLiteRunner {
|
||||
CreateDbFromSqlStatementsMethod() {
|
||||
// createDbFromSqlStatements(Context context, String dbName, int dbVersion, String sqlStatements)
|
||||
this.getDeclaringType() instanceof TypeDatabaseUtils and
|
||||
this.hasName("createDbFromSqlStatements")
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = 3 }
|
||||
}
|
||||
|
||||
private class QueryNumEntriesMethod extends SQLiteRunner {
|
||||
QueryNumEntriesMethod() {
|
||||
// queryNumEntries(SQLiteDatabase db, String table, String selection)
|
||||
// queryNumEntries(SQLiteDatabase db, String table, String selection, String[] selectionArgs)
|
||||
this.getDeclaringType() instanceof TypeDatabaseUtils and
|
||||
this.hasName("queryNumEntries")
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = 2 }
|
||||
}
|
||||
|
||||
private class QueryBuilderDeleteMethod extends SQLiteRunner {
|
||||
QueryBuilderDeleteMethod() {
|
||||
// delete(SQLiteDatabase db, String selection, String[] selectionArgs)
|
||||
this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and
|
||||
this.hasName("delete")
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = [-1, 1] }
|
||||
}
|
||||
|
||||
private class QueryBuilderInsertMethod extends SQLiteRunner {
|
||||
QueryBuilderInsertMethod() {
|
||||
// insert(SQLiteDatabase db, ContentValues values)
|
||||
this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and
|
||||
this.hasName("insert")
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = -1 }
|
||||
}
|
||||
|
||||
private class QueryBuilderQueryMethod extends SQLiteRunner {
|
||||
QueryBuilderQueryMethod() {
|
||||
// query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder)
|
||||
// query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit)
|
||||
// query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit, CancellationSignal cancellationSignal)
|
||||
this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and
|
||||
this.hasName("query")
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = [-1, 2, 4, 5, 6, 7] }
|
||||
}
|
||||
|
||||
private class QueryBuilderUpdateMethod extends SQLiteRunner {
|
||||
QueryBuilderUpdateMethod() {
|
||||
// update(SQLiteDatabase db, ContentValues values, String selection, String[] selectionArgs)
|
||||
this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and
|
||||
this.hasName("update")
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = [-1, 2] }
|
||||
}
|
||||
|
||||
private class ContentProviderDeleteMethod extends SQLiteRunner {
|
||||
ContentProviderDeleteMethod() {
|
||||
// delete(Uri uri, String selection, String[] selectionArgs)
|
||||
(
|
||||
this.getDeclaringType() instanceof AndroidContentProvider or
|
||||
this.getDeclaringType() instanceof AndroidContentResolver
|
||||
) and
|
||||
this.hasName("delete") and
|
||||
this.getNumberOfParameters() = 3
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = 1 }
|
||||
}
|
||||
|
||||
private class ContentProviderQueryMethod extends SQLiteRunner {
|
||||
ContentProviderQueryMethod() {
|
||||
// query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal)
|
||||
// query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
|
||||
(
|
||||
this.getDeclaringType() instanceof AndroidContentProvider or
|
||||
this.getDeclaringType() instanceof AndroidContentResolver
|
||||
) and
|
||||
this.hasName("query") and
|
||||
this.getNumberOfParameters() = [5, 6]
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = 2 }
|
||||
}
|
||||
|
||||
private class ContentProviderUpdateMethod extends SQLiteRunner {
|
||||
ContentProviderUpdateMethod() {
|
||||
// update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
|
||||
(
|
||||
this.getDeclaringType() instanceof AndroidContentProvider or
|
||||
this.getDeclaringType() instanceof AndroidContentResolver
|
||||
) and
|
||||
this.hasName("update") and
|
||||
this.getNumberOfParameters() = 4
|
||||
}
|
||||
|
||||
override int sqlIndex() { result = 2 }
|
||||
}
|
||||
|
||||
private class QueryBuilderBuildMethod extends TaintPreservingCallable {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* Methods annotated with this allow for generation of "plain SQL"
|
||||
@@ -21,3 +22,13 @@ predicate jOOQSqlMethod(Method m) {
|
||||
m.getAnAnnotation() instanceof PlainSQLType and
|
||||
m.getParameterType(0) instanceof TypeString
|
||||
}
|
||||
|
||||
private class SqlSinkCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
//"package;type;overrides;name;signature;ext;spec;kind"
|
||||
"org.jooq;PlainSQL;false;;;Annotated;Argument[0];sql"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,8 @@
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.frameworks.Jdbc
|
||||
import semmle.code.java.frameworks.jOOQ
|
||||
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
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/** A sink for database query language injection vulnerabilities. */
|
||||
abstract class QueryInjectionSink extends DataFlow::Node { }
|
||||
@@ -29,28 +24,7 @@ class AdditionalQueryInjectionTaintStep extends Unit {
|
||||
|
||||
/** 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
|
||||
if index = -1
|
||||
then this.asExpr() = ma.getQualifier()
|
||||
else 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)
|
||||
or
|
||||
index = 0 and jOOQSqlMethod(m)
|
||||
)
|
||||
}
|
||||
SqlInjectionSink() { sinkNode(this, "sql") }
|
||||
}
|
||||
|
||||
/** A sink for Java Persistence Query Language injection vulnerabilities. */
|
||||
|
||||
Reference in New Issue
Block a user