Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java: Identify more APIs as supported in the telemetry queries. #16297

Merged
merged 7 commits into from May 3, 2024
39 changes: 39 additions & 0 deletions java/ql/lib/semmle/code/java/dataflow/ApiSinks.qll
@@ -0,0 +1,39 @@
/** Provides classes representing various flow sinks for data flow / taint tracking. */

private import semmle.code.java.dataflow.FlowSinks as FlowSinks
owen-mc marked this conversation as resolved.
Show resolved Hide resolved

final class SinkNode = FlowSinks::ApiSinkNode;

/**
* Module that adds all API like sinks to `SinkNode`, excluding sinks for cryptography based
* queries, and queries where sinks are not succifiently defined (eg. using broad method name matching).
*/
private module AllApiSinks {
private import semmle.code.java.security.AndroidSensitiveCommunicationQuery
private import semmle.code.java.security.ArbitraryApkInstallation
private import semmle.code.java.security.CleartextStorageAndroidDatabaseQuery
private import semmle.code.java.security.CleartextStorageAndroidFilesystemQuery
private import semmle.code.java.security.CleartextStorageCookieQuery
private import semmle.code.java.security.CleartextStorageSharedPrefsQuery
private import semmle.code.java.security.ExternallyControlledFormatStringQuery
private import semmle.code.java.security.InsecureBasicAuth
private import semmle.code.java.security.IntentUriPermissionManipulation
private import semmle.code.java.security.InsecureLdapAuth
private import semmle.code.java.security.InsecureTrustManager
private import semmle.code.java.security.JndiInjection
private import semmle.code.java.security.JWT
private import semmle.code.java.security.OgnlInjection
private import semmle.code.java.security.SensitiveResultReceiverQuery
private import semmle.code.java.security.SensitiveUiQuery
private import semmle.code.java.security.SpelInjection
private import semmle.code.java.security.SpelInjectionQuery
private import semmle.code.java.security.QueryInjection
private import semmle.code.java.security.TempDirLocalInformationDisclosureQuery
private import semmle.code.java.security.UnsafeAndroidAccess
private import semmle.code.java.security.UnsafeContentUriResolution
private import semmle.code.java.security.UnsafeDeserializationQuery
private import semmle.code.java.security.UrlRedirect
private import semmle.code.java.security.WebviewDebuggingEnabledQuery
private import semmle.code.java.security.XPath
private import semmle.code.java.security.XSS
}
23 changes: 23 additions & 0 deletions java/ql/lib/semmle/code/java/dataflow/ApiSources.qll
@@ -0,0 +1,23 @@
/** Provides classes representing various flow sources for data flow / taint tracking. */

private import semmle.code.java.dataflow.FlowSources as FlowSources

final class SourceNode = FlowSources::ApiSourceNode;

/**
* Module that adds all API like sources to `SourceNode`, excluding some sources for cryptography based
* queries, and queries where sources are not succifiently defined (eg. using broad method name matching).
*/
private module AllApiSources {
private import semmle.code.java.security.ArbitraryApkInstallation
private import semmle.code.java.security.CleartextStorageAndroidDatabaseQuery
private import semmle.code.java.security.CleartextStorageAndroidFilesystemQuery
private import semmle.code.java.security.CleartextStorageCookieQuery
private import semmle.code.java.security.CleartextStorageSharedPrefsQuery
private import semmle.code.java.security.ImplicitPendingIntentsQuery
private import semmle.code.java.security.ImproperIntentVerificationQuery
private import semmle.code.java.security.InsecureTrustManager
private import semmle.code.java.security.JWT
private import semmle.code.java.security.StackTraceExposureQuery
private import semmle.code.java.security.ZipSlipQuery
}
18 changes: 18 additions & 0 deletions java/ql/lib/semmle/code/java/dataflow/FlowSinks.qll
@@ -0,0 +1,18 @@
/** Provides classes representing various flow sinks for data flow / taint tracking. */

private import java
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.DataFlow

/**
* A data flow sink node for an API, which should be considered
* supported for a modeling perspective.
*/
abstract class ApiSinkNode extends DataFlow::Node { }
Fixed Show fixed Hide fixed

/**
* Add all sink models as data sinks.
*/
private class ApiSinkNodeExternal extends ApiSinkNode {
ApiSinkNodeExternal() { sinkNode(this, _) }
}
23 changes: 20 additions & 3 deletions java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
Expand Up @@ -194,15 +194,17 @@ private class AndroidExternalStorageSource extends RemoteFlowSource {
}

/** Class for `tainted` user input. */
abstract class UserInput extends DataFlow::Node { }
abstract class UserInput extends SourceNode { }

/**
* Input that may be controlled by a remote user.
*/
private class RemoteUserInput extends UserInput instanceof RemoteFlowSource { }
private class RemoteUserInput extends UserInput instanceof RemoteFlowSource {
override string getThreatModel() { result = RemoteFlowSource.super.getThreatModel() }
}

/** A node with input that may be controlled by a local user. */
abstract class LocalUserInput extends UserInput, SourceNode {
abstract class LocalUserInput extends UserInput {
override string getThreatModel() { result = "local" }
}

Expand Down Expand Up @@ -385,3 +387,18 @@ class AndroidJavascriptInterfaceMethodParameter extends RemoteFlowSource {
result = "Parameter of method with JavascriptInterface annotation"
}
}

/**
* A data flow source node for an API, which should be considered
* supported for a modeling perspective.
*/
abstract class ApiSourceNode extends DataFlow::Node { }
Fixed Show fixed Hide fixed

private class AddSourceNodes extends ApiSourceNode instanceof SourceNode { }

/**
* Add all source models as data sources.
*/
private class ApiSourceNodeExternal extends ApiSourceNode {
ApiSourceNodeExternal() { sourceNode(this, _) }
}
Expand Up @@ -4,6 +4,7 @@ import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.android.Intent
import semmle.code.java.security.SensitiveActions
private import semmle.code.java.dataflow.FlowSinks

/**
* Gets regular expression for matching names of Android variables that indicate the value being held contains sensitive information.
Expand Down Expand Up @@ -151,17 +152,24 @@ deprecated class SensitiveCommunicationConfig extends TaintTracking::Configurati
}
}

/**
* A sensitive communication sink node.
*/
private class SensitiveCommunicationSink extends ApiSinkNode {
SensitiveCommunicationSink() {
isSensitiveBroadcastSink(this)
or
isStartActivityOrServiceSink(this)
}
}

/**
* Taint configuration tracking flow from variables containing sensitive information to broadcast Intents.
*/
module SensitiveCommunicationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveInfoExpr }

predicate isSink(DataFlow::Node sink) {
isSensitiveBroadcastSink(sink)
or
isStartActivityOrServiceSink(sink)
}
predicate isSink(DataFlow::Node sink) { sink instanceof SensitiveCommunicationSink }

/**
* Holds if broadcast doesn't specify receiving package name of the 3rd party app
Expand Down
Expand Up @@ -4,6 +4,7 @@ import java
import semmle.code.java.frameworks.android.Intent
import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSinks
private import semmle.code.java.dataflow.FlowSources

/** A string literal that represents the MIME type for Android APKs. */
Expand Down Expand Up @@ -48,7 +49,7 @@ class SetDataMethod extends Method {
}

/** A dataflow sink for the URI of an intent. */
class SetDataSink extends DataFlow::ExprNode {
class SetDataSink extends ApiSinkNode, DataFlow::ExprNode {
SetDataSink() {
exists(MethodCall ma |
this.getExpr() = ma.getQualifier() and
Expand All @@ -69,7 +70,7 @@ class UriConstructorMethod extends Method {
* A dataflow source representing the URIs which an APK not controlled by the
* application may come from. Including external storage and web URLs.
*/
class ExternalApkSource extends DataFlow::Node {
class ExternalApkSource extends ApiSourceNode {
ExternalApkSource() {
sourceNode(this, "android-external-storage-dir") or
this.asExpr().(MethodCall).getMethod() instanceof UriConstructorMethod or
Expand Down
Expand Up @@ -6,6 +6,8 @@ import semmle.code.java.frameworks.android.ContentProviders
import semmle.code.java.frameworks.android.Intent
import semmle.code.java.frameworks.android.SQLite
import semmle.code.java.security.CleartextStorageQuery
private import semmle.code.java.dataflow.FlowSinks
private import semmle.code.java.dataflow.FlowSources

private class LocalDatabaseCleartextStorageSink extends CleartextStorageSink {
LocalDatabaseCleartextStorageSink() { localDatabaseInput(_, this.asExpr()) }
Expand Down Expand Up @@ -96,15 +98,24 @@ private predicate localDatabaseStore(DataFlow::Node database, MethodCall store)
)
}

/**
* A local database open method call source node.
*/
private class LocalDatabaseOpenMethodCallSource extends ApiSourceNode {
LocalDatabaseOpenMethodCallSource() { this.asExpr() instanceof LocalDatabaseOpenMethodCall }
}

/**
* A local database sink node.
*/
private class LocalDatabaseSink extends ApiSinkNode {
LocalDatabaseSink() { localDatabaseInput(this, _) or localDatabaseStore(this, _) }
}

private module LocalDatabaseFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof LocalDatabaseOpenMethodCall
}
predicate isSource(DataFlow::Node source) { source instanceof LocalDatabaseOpenMethodCallSource }

predicate isSink(DataFlow::Node sink) {
localDatabaseInput(sink, _) or
localDatabaseStore(sink, _)
}
predicate isSink(DataFlow::Node sink) { sink instanceof LocalDatabaseSink }

predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
// Adds a step for tracking databases through field flow, that is, a database is opened and
Expand Down
Expand Up @@ -5,9 +5,11 @@

import java
import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.security.CleartextStorageQuery
import semmle.code.xml.AndroidManifest
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSinks
private import semmle.code.java.dataflow.FlowSources

private class AndroidFilesystemCleartextStorageSink extends CleartextStorageSink {
AndroidFilesystemCleartextStorageSink() {
Expand Down Expand Up @@ -79,13 +81,27 @@ private class CloseFileMethod extends Method {
}
}

private module FilesystemFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof LocalFileOpenCall }
/**
* A local file open call source node.
*/
private class LocalFileOpenCallSource extends ApiSourceNode {
LocalFileOpenCallSource() { this.asExpr() instanceof LocalFileOpenCall }
}

predicate isSink(DataFlow::Node sink) {
filesystemInput(sink, _) or
closesFile(sink, _)
/**
* A local file sink node.
*/
private class LocalFileSink extends ApiSinkNode {
LocalFileSink() {
filesystemInput(this, _) or
closesFile(this, _)
}
}

private module FilesystemFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src instanceof LocalFileOpenCallSource }

predicate isSink(DataFlow::Node sink) { sink instanceof LocalFileSink }

predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
// Add nested Writer constructors as extra data flow steps
Expand Down
Expand Up @@ -4,6 +4,8 @@ import java
import semmle.code.java.dataflow.DataFlow
deprecated import semmle.code.java.dataflow.DataFlow3
import semmle.code.java.security.CleartextStorageQuery
private import semmle.code.java.dataflow.FlowSinks
private import semmle.code.java.dataflow.FlowSources

private class CookieCleartextStorageSink extends CleartextStorageSink {
CookieCleartextStorageSink() { this.asExpr() = cookieInput(_) }
Expand Down Expand Up @@ -37,10 +39,24 @@ private predicate cookieStore(DataFlow::Node cookie, Expr store) {
)
}

/**
* A cookie source node.
*/
private class CookieSource extends ApiSourceNode {
CookieSource() { this.asExpr() instanceof Cookie }
}

/**
* A cookie store sink node.
*/
private class CookieStoreSink extends ApiSinkNode {
CookieStoreSink() { cookieStore(this, _) }
}

private module CookieToStoreFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof Cookie }
predicate isSource(DataFlow::Node src) { src instanceof CookieSource }

predicate isSink(DataFlow::Node sink) { cookieStore(sink, _) }
predicate isSink(DataFlow::Node sink) { sink instanceof CookieStoreSink }
}

private module CookieToStoreFlow = DataFlow::Global<CookieToStoreFlowConfig>;
Expand Down
Expand Up @@ -4,6 +4,8 @@ import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.frameworks.android.SharedPreferences
import semmle.code.java.security.CleartextStorageQuery
private import semmle.code.java.dataflow.FlowSinks
private import semmle.code.java.dataflow.FlowSources

private class SharedPrefsCleartextStorageSink extends CleartextStorageSink {
SharedPrefsCleartextStorageSink() {
Expand Down Expand Up @@ -67,16 +69,30 @@ private predicate sharedPreferencesStore(DataFlow::Node editor, MethodCall m) {
editor.asExpr() = m.getQualifier().getUnderlyingExpr()
}

/** Flow from `SharedPreferences.Editor` to either a setter or a store method. */
private module SharedPreferencesFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
src.asExpr() instanceof SharedPreferencesEditorMethodCall
/**
* A shared preferences editor method call source node.
*/
private class SharedPreferencesEditorMethodCallSource extends ApiSourceNode {
SharedPreferencesEditorMethodCallSource() {
this.asExpr() instanceof SharedPreferencesEditorMethodCall
}
}

predicate isSink(DataFlow::Node sink) {
sharedPreferencesInput(sink, _) or
sharedPreferencesStore(sink, _)
/**
* A shared preferences sink node.
*/
private class SharedPreferencesSink extends ApiSinkNode {
SharedPreferencesSink() {
sharedPreferencesInput(this, _) or
sharedPreferencesStore(this, _)
}
}

/** Flow from `SharedPreferences.Editor` to either a setter or a store method. */
private module SharedPreferencesFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src instanceof SharedPreferencesEditorMethodCallSource }

predicate isSink(DataFlow::Node sink) { sink instanceof SharedPreferencesSink }
}

private module SharedPreferencesFlow = DataFlow::Global<SharedPreferencesFlowConfig>;
@@ -1,18 +1,24 @@
/** Provides a taint-tracking configuration to reason about externally controlled format string vulnerabilities. */

import java
private import semmle.code.java.dataflow.FlowSinks
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.StringFormat

/**
* A string format sink node.
*/
private class StringFormatSink extends ApiSinkNode {
StringFormatSink() { this.asExpr() = any(StringFormat formatCall).getFormatArgument() }
}

/**
* A taint-tracking configuration for externally controlled format string vulnerabilities.
*/
module ExternallyControlledFormatStringConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }

predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(StringFormat formatCall).getFormatArgument()
}
predicate isSink(DataFlow::Node sink) { sink instanceof StringFormatSink }

predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof NumericType or node.getType() instanceof BooleanType
Expand Down