Skip to content

Commit

Permalink
Merge pull request #16297 from michaelnebel/java/improveapitelemetry
Browse files Browse the repository at this point in the history
Java: Identify more APIs as supported in the telemetry queries.
  • Loading branch information
michaelnebel committed May 3, 2024
2 parents 75615f2 + c07bf65 commit 95ff5ba
Show file tree
Hide file tree
Showing 37 changed files with 329 additions and 92 deletions.
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

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 { }

/**
* 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 { }

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

0 comments on commit 95ff5ba

Please sign in to comment.