mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
Java: add Android database taint and SQL injection sinks
This commit is contained in:
@@ -387,6 +387,17 @@ private predicate taintPreservingQualifierToMethod(Method m) {
|
||||
stringlist.getTypeArgument(0) instanceof TypeString
|
||||
)
|
||||
)
|
||||
or
|
||||
m
|
||||
.getDeclaringType()
|
||||
.getASourceSupertype*()
|
||||
.hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and
|
||||
// buildQuery(String[] projectionIn, String selection, String groupBy, String having, String sortOrder, String limit)
|
||||
// buildQuery(String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit)
|
||||
// buildUnionQuery(String[] subQueries, String sortOrder, String limit)
|
||||
// buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set<String> columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String[] selectionArgs, String groupBy, String having)
|
||||
// buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set<String> columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String groupBy, String having)
|
||||
m.hasName(["buildQuery", "buildUnionQuery", "buildUnionSubQuery"])
|
||||
}
|
||||
|
||||
private class StringReplaceMethod extends Method {
|
||||
@@ -447,6 +458,20 @@ private predicate argToMethodStep(Expr tracked, MethodAccess sink) {
|
||||
private predicate taintPreservingArgumentToMethod(Method method) {
|
||||
method.getDeclaringType() instanceof TypeString and
|
||||
(method.hasName("format") or method.hasName("formatted") or method.hasName("join"))
|
||||
or
|
||||
method.getDeclaringType().hasQualifiedName("android.database", "DatabaseUtils") and
|
||||
// String[] appendSelectionArgs(String[] originalValues, String[] newValues)
|
||||
// String concatenateWhere(String a, String b)
|
||||
method.hasName(["appendSelectionArgs", "concatenateWhere"])
|
||||
or
|
||||
method
|
||||
.getDeclaringType()
|
||||
.getASourceSupertype*()
|
||||
.hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and
|
||||
// buildQuery(String[] projectionIn, String selection, String groupBy, String having, String sortOrder, String limit)
|
||||
// buildQuery(String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit)
|
||||
// buildUnionQuery(String[] subQueries, String sortOrder, String limit)
|
||||
method.hasName(["buildQuery", "buildUnionQuery"])
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,6 +585,18 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
|
||||
method.getDeclaringType().hasQualifiedName("java.io", "StringWriter") and
|
||||
method.hasName("append") and
|
||||
arg = 0
|
||||
or
|
||||
method.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and
|
||||
(
|
||||
// static buildQueryString(boolean distinct, String tables, String[] columns, String where, String groupBy, String having, String orderBy, String limit)
|
||||
method.hasName("buildQueryString") and arg = [1 .. method.getNumberOfParameters()]
|
||||
or
|
||||
// buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set<String> columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String[] selectionArgs, String groupBy, String having)
|
||||
// buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set<String> columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String groupBy, String having)
|
||||
method.hasName("buildUnionSubQuery") and
|
||||
arg = [0 .. method.getNumberOfParameters()] and
|
||||
arg != 3
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -612,6 +649,12 @@ private predicate taintPreservingArgToArg(Method method, int input, int output)
|
||||
method.getNumberOfParameters() > 1 and
|
||||
input = method.getNumberOfParameters() - 1 and
|
||||
output = 0
|
||||
or
|
||||
method.getDeclaringType().hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and
|
||||
// static appendColumns(StringBuilder s, String[] columns)
|
||||
method.hasName("appendColumns") and
|
||||
input = 1 and
|
||||
output = 0
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -649,6 +692,17 @@ private predicate taintPreservingArgumentToQualifier(Method method, int arg) {
|
||||
arg = 0 and
|
||||
append.getDeclaringType().hasQualifiedName("java.io", "StringWriter")
|
||||
)
|
||||
or
|
||||
method
|
||||
.getDeclaringType()
|
||||
.getASourceSupertype*()
|
||||
.hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and
|
||||
// setProjectionMap(Map<String, String> columnMap)
|
||||
// setTables(String inTables)
|
||||
// appendWhere(CharSequence inWhere)
|
||||
// appendWhereStandalone(CharSequence inWhere)
|
||||
method.hasName(["setProjectionMap", "setTables", "appendWhere", "appendWhereStandalone"]) and
|
||||
arg = 0
|
||||
}
|
||||
|
||||
/** A comparison or equality test with a constant. */
|
||||
|
||||
@@ -90,3 +90,127 @@ 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())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user