mirror of
https://github.com/github/codeql.git
synced 2025-12-21 03:06:31 +01:00
Merge branch 'main' into post-release-prep/codeql-cli-2.8.0
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
/**
|
||||
* @name Diagnostics for framework coverage
|
||||
* @description Expose diagnostics for the number of API endpoints covered by CSV models.
|
||||
* @kind diagnostic
|
||||
* @id java/diagnostics/framework-coverage
|
||||
* @id java/summary/framework-coverage
|
||||
* @name Metrics of framework coverage
|
||||
* @description Expose metrics for the number of API endpoints covered by CSV models.
|
||||
* @kind metric
|
||||
* @tags summary
|
||||
*/
|
||||
|
||||
import java
|
||||
@@ -0,0 +1,27 @@
|
||||
public void sqliteStorageUnsafe(Context ctx, String name, String password) {
|
||||
// BAD - sensitive information saved in cleartext.
|
||||
SQLiteDatabase db = ctx.openOrCreateDatabase("test", Context.MODE_PRIVATE, null);
|
||||
db.execSQL("INSERT INTO users VALUES (?, ?)", new String[] {name, password});
|
||||
}
|
||||
|
||||
public void sqliteStorageSafe(Context ctx, String name, String password) {
|
||||
// GOOD - sensitive information encrypted with a custom method.
|
||||
SQLiteDatabase db = ctx.openOrCreateDatabase("test", Context.MODE_PRIVATE, null);
|
||||
db.execSQL("INSERT INTO users VALUES (?, ?)", new String[] {name, encrypt(password)});
|
||||
}
|
||||
|
||||
public void sqlCipherStorageSafe(String name, String password, String databasePassword) {
|
||||
// GOOD - sensitive information saved using SQLCipher.
|
||||
net.sqlcipher.database.SQLiteDatabase db =
|
||||
net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase("test", databasePassword, null);
|
||||
db.execSQL("INSERT INTO users VALUES (?, ?)", new String[] {name, password});
|
||||
}
|
||||
|
||||
private static String encrypt(String cleartext) {
|
||||
// Use an encryption or strong hashing algorithm in the real world.
|
||||
// The example below just returns a SHA-256 hash.
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] hash = digest.digest(cleartext.getBytes(StandardCharsets.UTF_8));
|
||||
String encoded = Base64.getEncoder().encodeToString(hash);
|
||||
return encoded;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
SQLite is a lightweight database engine commonly used in Android devices to store data. By itself, SQLite does not offer any encryption mechanism by default and stores all data in cleartext, which introduces a risk if sensitive data like credentials, authentication tokens or personal identifiable information (PII) are directly stored in a SQLite database. The information could be accessed by any process or user in rooted devices, or can be disclosed through chained vulnerabilities, like unexpected access to the private storage through exposed components.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Use <code>SQLCipher</code> or similar libraries to add encryption capabilities to SQLite. Alternatively, encrypt sensitive data using cryptographically secure algorithms before storing it in the database.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the first example, sensitive user information is stored in cleartext.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the second and third examples, the code encrypts sensitive information before saving it to the database.
|
||||
</p>
|
||||
<sample src="CleartextStorageAndroidDatabase.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Android Developers:
|
||||
<a href="https://developer.android.com/topic/security/data">Work with data more securely</a>
|
||||
</li>
|
||||
<li>
|
||||
SQLCipher:
|
||||
<a href="https://www.zetetic.net/sqlcipher/sqlcipher-for-android/">Android Application Integration</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @name Cleartext storage of sensitive information using a local database on Android
|
||||
* @description Cleartext Storage of Sensitive Information using
|
||||
* a local database on Android allows access for users with root
|
||||
* privileges or unexpected exposure from chained vulnerabilities.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @id java/android/cleartext-storage-database
|
||||
* @tags security
|
||||
* external/cwe/cwe-312
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.CleartextStorageAndroidDatabaseQuery
|
||||
|
||||
from SensitiveSource data, LocalDatabaseOpenMethodAccess s, Expr input, Expr store
|
||||
where
|
||||
input = s.getAnInput() and
|
||||
store = s.getAStore() and
|
||||
data.flowsTo(input)
|
||||
select store, "SQLite database $@ containing $@ is stored $@. Data was added $@.", s, s.toString(),
|
||||
data, "sensitive data", store, "here", input, "here"
|
||||
@@ -2,7 +2,7 @@
|
||||
* @name External libraries
|
||||
* @description A list of external libraries used in the code
|
||||
* @kind metric
|
||||
* @metricType callable
|
||||
* @tags summary
|
||||
* @id java/telemetry/external-libs
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* @name Supported sinks in external libraries
|
||||
* @description A list of 3rd party APIs detected as sinks. Excludes test and generated code.
|
||||
* @id java/telemetry/supported-external-api-sinks
|
||||
* @kind metric
|
||||
* @metricType callable
|
||||
* @tags summary
|
||||
* @id java/telemetry/supported-external-api-sinks
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* @name Supported sources in external libraries
|
||||
* @description A list of 3rd party APIs detected as sources. Excludes test and generated code.
|
||||
* @id java/telemetry/supported-external-api-sources
|
||||
* @kind metric
|
||||
* @metricType callable
|
||||
* @tags summary
|
||||
* @id java/telemetry/supported-external-api-sources
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* @name Supported sinks in external libraries
|
||||
* @description A list of 3rd party APIs detected as sinks. Excludes test and generated code.
|
||||
* @id java/telemetry/supported-external-api-taint
|
||||
* @name Supported flow steps in external libraries
|
||||
* @description A list of 3rd party APIs detected as flow steps. Excludes test and generated code.
|
||||
* @kind metric
|
||||
* @metricType callable
|
||||
* @tags summary
|
||||
* @id java/telemetry/supported-external-api-taint
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* @name Usage of unsupported APIs coming from external libraries
|
||||
* @description A list of 3rd party APIs used in the codebase. Excludes test and generated code.
|
||||
* @id java/telemetry/unsupported-external-api
|
||||
* @kind metric
|
||||
* @metricType callable
|
||||
* @tags summary
|
||||
* @id java/telemetry/unsupported-external-api
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* A new query "Cleartext storage of sensitive information using a local database on Android" (`java/android/cleartext-storage-database`) has been added. This query finds instances of sensitive data being stored in local databases without encryption, which may expose it to attackers or malicious applications.
|
||||
@@ -1,9 +1,11 @@
|
||||
name: codeql/java-queries
|
||||
version: 0.0.9-dev
|
||||
groups: java
|
||||
groups:
|
||||
- java
|
||||
- queries
|
||||
suites: codeql-suites
|
||||
extractor: java
|
||||
defaultSuiteFile: codeql-suites/java-code-scanning.qls
|
||||
dependencies:
|
||||
codeql/java-all: "*"
|
||||
codeql/suite-helpers: "*"
|
||||
codeql/java-all: "*"
|
||||
codeql/suite-helpers: "*"
|
||||
|
||||
53
java/ql/src/utils/model-generator/RegenerateModels.py
Executable file
53
java/ql/src/utils/model-generator/RegenerateModels.py
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
# Tool to regenerate existing framework CSV models.
|
||||
|
||||
from pathlib import Path
|
||||
import json
|
||||
import os
|
||||
import requests
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import sys
|
||||
|
||||
|
||||
defaultModelPath = "java/ql/lib/semmle/code/java/frameworks"
|
||||
lgtmSlugToModelFile = {
|
||||
# "apache/commons-beanutils": "apache/BeanUtilsGenerated.qll",
|
||||
# "apache/commons-codec": "apache/CodecGenerated.qll",
|
||||
# "apache/commons-lang": "apache/Lang3Generated.qll",
|
||||
"apache/commons-io": "apache/IOGenerated.qll",
|
||||
}
|
||||
|
||||
|
||||
def findGitRoot():
|
||||
return subprocess.check_output(
|
||||
["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip()
|
||||
|
||||
|
||||
def regenerateModel(lgtmSlug, extractedDb):
|
||||
tmpDir = tempfile.mkdtemp()
|
||||
print("============================================================")
|
||||
print("Generating models for " + lgtmSlug)
|
||||
print("============================================================")
|
||||
# check if lgtmSlug exists as key
|
||||
if lgtmSlug not in lgtmSlugToModelFile:
|
||||
print("ERROR: slug " + lgtmSlug +
|
||||
" is not mapped to a model file in script " + sys.argv[0])
|
||||
sys.exit(1)
|
||||
modelFile = defaultModelPath + "/" + lgtmSlugToModelFile[lgtmSlug]
|
||||
codeQlRoot = findGitRoot()
|
||||
targetModel = codeQlRoot + "/" + modelFile
|
||||
subprocess.check_call([codeQlRoot + "/java/ql/src/utils/model-generator/GenerateFlowModel.py", extractedDb,
|
||||
targetModel])
|
||||
print("Regenerated " + targetModel)
|
||||
shutil.rmtree(tmpDir)
|
||||
|
||||
|
||||
if len(sys.argv) == 3:
|
||||
lgtmSlug = sys.argv[1]
|
||||
db = sys.argv[2]
|
||||
regenerateModel(lgtmSlug, db)
|
||||
else:
|
||||
print('error')
|
||||
Reference in New Issue
Block a user