Move query sinks into SQLite.qll

This commit is contained in:
Arthur Baars
2020-09-28 19:28:43 +02:00
parent b3aae276ba
commit 28c965765b
2 changed files with 165 additions and 130 deletions

View File

@@ -1,4 +1,5 @@
import java
import Android
/**
* The class `android.database.sqlite.SQLiteDatabase`.
@@ -28,7 +29,10 @@ abstract class SQLiteRunner extends Method {
class ExecSqlMethod extends SQLiteRunner {
ExecSqlMethod() {
this.getDeclaringType() instanceof TypeSQLiteDatabase and
this.getName() = "execSql"
// execPerConnectionSQL(String sql, Object[] bindArgs)
// execSQL(String sql)
// execSQL(String sql, Object[] bindArgs)
this.hasName(["execPerConnectionSQL", "execSQL"])
}
override int sqlIndex() { result = 0 }
@@ -37,26 +41,179 @@ class ExecSqlMethod extends SQLiteRunner {
class QueryMethod extends SQLiteRunner {
QueryMethod() {
this.getDeclaringType() instanceof TypeSQLiteDatabase and
this.getName().matches("rawQuery%")
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 = 2 else result = 3)
(
if this.getParameter(0).getType() instanceof TypeString
then result = [2, 4, 5, 6, 7]
else result = [3, 5, 6, 7, 8]
)
or
this.getName() = "queryWithFactory" and result = 4
// 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 = [4, 6, 7, 8, 9]
}
}
class RawQueryMethod extends SQLiteRunner {
RawQueryMethod() {
this.getDeclaringType() instanceof TypeSQLiteDatabase and
this.getName().matches("rawQuery%")
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
}
}
class CompileStatementMethod extends SQLiteRunner {
CompileStatementMethod() {
this.getDeclaringType() instanceof TypeSQLiteDatabase and
// compileStatement(String sql)
this.hasName("compileStatement")
}
override int sqlIndex() { result = 0 }
}
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 }
}
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 }
}
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 }
}
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 }
}
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 }
}
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] }
}
class QueryBuilderInsertMethod extends SQLiteRunner {
QueryBuilderInsertMethod() {
// insert(SQLiteDatabase db, ContentValues values)
this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and
this.hasName("insert")
}
override int sqlIndex() { result = -1 }
}
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, 3, 5, 6, 7, 8] }
}
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] }
}
class ContentProviderDeleteMethod extends SQLiteRunner {
ContentProviderDeleteMethod() {
// delete(Uri uri, String selection, String[] selectionArgs)
this.getDeclaringType() instanceof AndroidContentProvider and
this.hasName("delete") and
this.getNumberOfParameters() = 3
}
override int sqlIndex() { result = 1 }
}
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 and
this.hasName("query") and
this.getNumberOfParameters() = [5, 6]
}
override int sqlIndex() { result = 2 }
}
class ContentProviderUpdateMethod extends SQLiteRunner {
ContentProviderUpdateMethod() {
// update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
this.getDeclaringType() instanceof AndroidContentProvider and
this.hasName("update") and
this.getNumberOfParameters() = 4
}
override int sqlIndex() { result = 2 }
}

View File

@@ -34,7 +34,9 @@ private class SqlInjectionSink extends QueryInjectionSink {
or
exists(MethodAccess ma, Method m, int index |
ma.getMethod() = m and
ma.getArgument(index) = this.asExpr()
if index = -1
then this.asExpr() = ma.getQualifier()
else ma.getArgument(index) = this.asExpr()
|
index = m.(SQLiteRunner).sqlIndex()
or
@@ -90,127 +92,3 @@ private class MongoJsonStep extends AdditionalQueryInjectionTaintStep {
)
}
}
/** A sink for Android database injection vulnerabilities. */
private class AndroidDatabaseUtils extends QueryInjectionSink {
AndroidDatabaseUtils() {
exists(MethodAccess call, Method method |
method = call.getMethod() and
method.getDeclaringType().hasQualifiedName("android.database", "DatabaseUtils") and
(
// (blobFileDescriptor|long|string)ForQuery(SQLiteDatabase db, String query, String[] selectionArgs)
method.hasName(["blobFileDescriptorForQuery", "longForQuery", "stringForQuery"]) and
method.getNumberOfParameters() = 3 and
this.asExpr() = call.getArgument(1)
or
// createDbFromSqlStatements(Context context, String dbName, int dbVersion, String sqlStatements)
method.hasName("createDbFromSqlStatements") and
this.asExpr() = call.getArgument(3)
or
// queryNumEntries(SQLiteDatabase db, String table, String selection)
// queryNumEntries(SQLiteDatabase db, String table, String selection, String[] selectionArgs)
method.hasName("queryNumEntries") and
this.asExpr() = call.getArgument(2)
)
or
method
.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName("android.database.sqlite", "SQLiteDatabase") and
(
// compileStatement(String sql)
method.hasName("compileStatement") and
this.asExpr() = call.getArgument(0)
or
// delete(String table, String whereClause, String[] whereArgs)
method.hasName("delete") and
this.asExpr() = call.getArgument(1)
or
// execPerConnectionSQL(String sql, Object[] bindArgs)
// execSQL(String sql)
// execSQL(String sql, Object[] bindArgs)
method.hasName(["execPerConnectionSQL", "execSQL"]) and
this.asExpr() = call.getArgument(0)
or
// 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)
method.hasName("query") and
(
this.asExpr() = call.getArgument([3, 5, 6, 7, 8]) and
method.getNumberOfParameters() = [9, 10]
or
this.asExpr() = call.getArgument([2, 4, 5, 6, 7]) and
method.getNumberOfParameters() = [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)
method.hasName("queryWithFactory") and
this.asExpr() = call.getArgument([4, 6, 7, 8, 9])
or
// rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal)
// rawQuery(String sql, String[] selectionArgs)
method.hasName("rawQuery") and
this.asExpr() = call.getArgument(0)
or
// rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable, CancellationSignal cancellationSignal)
// rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable)
method.hasName("rawQueryWithFactory") and
this.asExpr() = call.getArgument(1)
or
// update(String table, ContentValues values, String whereClause, String[] whereArgs)
// updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm)
method.hasName(["update", "updateWithOnConflict"]) and
this.asExpr() = call.getArgument(2)
)
or
method
.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName("android.content", "ContentProvider") and
(
// delete(Uri uri, String selection, String[] selectionArgs)
method.hasName("delete") and
this.asExpr() = call.getArgument(1) and
method.getNumberOfParameters() = 3
or
// query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal)
// query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
method.hasName("query") and
method.getNumberOfParameters() = [5, 6] and
this.asExpr() = call.getArgument(2)
or
// update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
method.hasName("update") and
this.asExpr() = call.getArgument(2) and
method.getNumberOfParameters() = 4
)
or
method
.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and
(
// delete(SQLiteDatabase db, String selection, String[] selectionArgs)
method.hasName("delete") and
(this.asExpr() = call.getArgument(1) or this.asExpr() = call.getQualifier())
or
// insert(SQLiteDatabase db, ContentValues values)
method.hasName("update") and
this.asExpr() = call.getQualifier()
or
// 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)
method.hasName("query") and
(this.asExpr() = call.getArgument([3, 5, 6, 7, 8]) or this.asExpr() = call.getQualifier())
or
// update(SQLiteDatabase db, ContentValues values, String selection, String[] selectionArgs)
method.hasName("update") and
(this.asExpr() = call.getArgument(2) or this.asExpr() = call.getQualifier())
)
)
}
}