mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
Java: Identify more APIs as supported in the telemetry queries (as QL defined sinks).
This commit is contained in:
122
java/ql/lib/semmle/code/java/dataflow/ApiSinks.qll
Normal file
122
java/ql/lib/semmle/code/java/dataflow/ApiSinks.qll
Normal file
@@ -0,0 +1,122 @@
|
||||
/** Provides classes representing various flow sinks for data flow / taint tracking. */
|
||||
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* A data flow sink node.
|
||||
*/
|
||||
abstract class SinkNode extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* 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 ApiSinks {
|
||||
private import semmle.code.java.security.AndroidSensitiveCommunicationQuery as AndroidSensitiveCommunicationQuery
|
||||
private import semmle.code.java.security.ArbitraryApkInstallation as ArbitraryApkInstallation
|
||||
private import semmle.code.java.security.CleartextStorageAndroidDatabaseQuery as CleartextStorageAndroidDatabaseQuery
|
||||
private import semmle.code.java.security.CleartextStorageAndroidFilesystemQuery as CleartextStorageAndroidFilesystemQuery
|
||||
private import semmle.code.java.security.CleartextStorageCookieQuery as CleartextStorageCookieQuery
|
||||
private import semmle.code.java.security.CleartextStorageSharedPrefsQuery as CleartextStorageSharedPrefsQuery
|
||||
private import semmle.code.java.security.ExternallyControlledFormatStringQuery as ExternallyControlledFormatStringQuery
|
||||
private import semmle.code.java.security.InsecureBasicAuth as InsecureBasicAuth
|
||||
private import semmle.code.java.security.IntentUriPermissionManipulation as IntentUriPermissionManipulation
|
||||
private import semmle.code.java.security.InsecureLdapAuth as InsecureLdapAuth
|
||||
private import semmle.code.java.security.InsecureTrustManager as InsecureTrustManager
|
||||
private import semmle.code.java.security.JndiInjection as JndiInjection
|
||||
private import semmle.code.java.security.JWT as Jwt
|
||||
private import semmle.code.java.security.OgnlInjection as OgnlInjection
|
||||
private import semmle.code.java.security.SensitiveResultReceiverQuery as SensitiveResultReceiverQuery
|
||||
private import semmle.code.java.security.SensitiveUiQuery as SensitiveUiQuery
|
||||
private import semmle.code.java.security.SpelInjection as SpelInjection
|
||||
private import semmle.code.java.security.SpelInjectionQuery as SpelInjectionQuery
|
||||
private import semmle.code.java.security.QueryInjection as QueryInjection
|
||||
private import semmle.code.java.security.TempDirLocalInformationDisclosureQuery as TempDirLocalInformationDisclosureQuery
|
||||
private import semmle.code.java.security.UnsafeAndroidAccess as UnsafeAndroidAccess
|
||||
private import semmle.code.java.security.UnsafeContentUriResolution as UnsafeContentUriResolution
|
||||
private import semmle.code.java.security.UnsafeDeserializationQuery as UnsafeDeserializationQuery
|
||||
private import semmle.code.java.security.UrlRedirect as UrlRedirect
|
||||
private import semmle.code.java.security.WebviewDebuggingEnabledQuery as WebviewDebuggingEnabledQuery
|
||||
private import semmle.code.java.security.XPath as Xpath
|
||||
private import semmle.code.java.security.XSS as Xss
|
||||
|
||||
private class AndoidIntentRedirectionQuerySinks extends SinkNode instanceof AndroidSensitiveCommunicationQuery::SensitiveCommunicationSink
|
||||
{ }
|
||||
|
||||
private class ArbitraryApkInstallationSinks extends SinkNode instanceof ArbitraryApkInstallation::SetDataSink
|
||||
{ }
|
||||
|
||||
private class CleartextStorageAndroidDatabaseQuerySinks extends SinkNode instanceof CleartextStorageAndroidDatabaseQuery::LocalDatabaseSink
|
||||
{ }
|
||||
|
||||
private class CleartextStorageAndroidFilesystemQuerySinks extends SinkNode instanceof CleartextStorageAndroidFilesystemQuery::LocalFileSink
|
||||
{ }
|
||||
|
||||
private class CleartextStorageCookieQuerySinks extends SinkNode instanceof CleartextStorageCookieQuery::CookieStoreSink
|
||||
{ }
|
||||
|
||||
private class CleartextStorageSharedPrefsQuerySinks extends SinkNode instanceof CleartextStorageSharedPrefsQuery::SharedPreferencesSink
|
||||
{ }
|
||||
|
||||
private class ExternallyControlledFormatStringQuerySinks extends SinkNode instanceof ExternallyControlledFormatStringQuery::StringFormatSink
|
||||
{ }
|
||||
|
||||
private class InsecureBasicAuthSinks extends SinkNode instanceof InsecureBasicAuth::InsecureBasicAuthSink
|
||||
{ }
|
||||
|
||||
private class InsecureTrustManagerSinks extends SinkNode instanceof InsecureTrustManager::InsecureTrustManagerSink
|
||||
{ }
|
||||
|
||||
private class IntentUriPermissionManipulationSinks extends SinkNode instanceof IntentUriPermissionManipulation::IntentUriPermissionManipulationSink
|
||||
{ }
|
||||
|
||||
private class InsecureLdapAuthSinks extends SinkNode instanceof InsecureLdapAuth::InsecureLdapUrlSink
|
||||
{ }
|
||||
|
||||
private class JndiInjectionSinks extends SinkNode instanceof JndiInjection::JndiInjectionSink { }
|
||||
|
||||
private class JwtSinks extends SinkNode instanceof Jwt::JwtParserWithInsecureParseSink { }
|
||||
|
||||
private class OgnlInjectionSinks extends SinkNode instanceof OgnlInjection::OgnlInjectionSink { }
|
||||
|
||||
private class SensitiveResultReceiverQuerySinks extends SinkNode instanceof SensitiveResultReceiverQuery::SensitiveResultReceiverSink
|
||||
{ }
|
||||
|
||||
private class SensitiveUiQuerySinks extends SinkNode instanceof SensitiveUiQuery::TextFieldSink {
|
||||
}
|
||||
|
||||
private class SpelInjectionSinks extends SinkNode instanceof SpelInjection::SpelExpressionEvaluationSink
|
||||
{ }
|
||||
|
||||
private class QueryInjectionSinks extends SinkNode instanceof QueryInjection::QueryInjectionSink {
|
||||
}
|
||||
|
||||
private class TempDirLocalInformationDisclosureSinks extends SinkNode instanceof TempDirLocalInformationDisclosureQuery::MethodFileDirectoryCreationSink
|
||||
{ }
|
||||
|
||||
private class UnsafeAndroidAccessSinks extends SinkNode instanceof UnsafeAndroidAccess::UrlResourceSink
|
||||
{ }
|
||||
|
||||
private class UnsafeContentUriResolutionSinks extends SinkNode instanceof UnsafeContentUriResolution::ContentUriResolutionSink
|
||||
{ }
|
||||
|
||||
private class UnsafeDeserializationQuerySinks extends SinkNode instanceof UnsafeDeserializationQuery::UnsafeDeserializationSink
|
||||
{ }
|
||||
|
||||
private class UrlRedirectSinks extends SinkNode instanceof UrlRedirect::UrlRedirectSink { }
|
||||
|
||||
private class WebviewDebugEnabledQuery extends SinkNode instanceof WebviewDebuggingEnabledQuery::WebviewDebugSink
|
||||
{ }
|
||||
|
||||
private class XPathSinks extends SinkNode instanceof Xpath::XPathInjectionSink { }
|
||||
|
||||
private class XssSinks extends SinkNode instanceof Xss::XssSink { }
|
||||
|
||||
/**
|
||||
* Add all models as data sinks.
|
||||
*/
|
||||
private class SinkNodeExternal extends SinkNode {
|
||||
SinkNodeExternal() { sinkNode(this, _) }
|
||||
}
|
||||
}
|
||||
@@ -151,17 +151,24 @@ deprecated class SensitiveCommunicationConfig extends TaintTracking::Configurati
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class of sensitive communication sink nodes.
|
||||
*/
|
||||
class SensitiveCommunicationSink extends DataFlow::Node {
|
||||
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
|
||||
|
||||
@@ -103,13 +103,17 @@ class LocalDatabaseOpenMethodCallSource extends DataFlow::Node {
|
||||
LocalDatabaseOpenMethodCallSource() { this.asExpr() instanceof LocalDatabaseOpenMethodCall }
|
||||
}
|
||||
|
||||
/**
|
||||
* A class of local database sink nodes.
|
||||
*/
|
||||
class LocalDatabaseSink extends DataFlow::Node {
|
||||
LocalDatabaseSink() { localDatabaseInput(this, _) or localDatabaseStore(this, _) }
|
||||
}
|
||||
|
||||
private module LocalDatabaseFlowConfig implements DataFlow::ConfigSig {
|
||||
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
|
||||
|
||||
@@ -86,13 +86,20 @@ class LocalFileOpenCallSource extends DataFlow::Node {
|
||||
LocalFileOpenCallSource() { this.asExpr() instanceof LocalFileOpenCall }
|
||||
}
|
||||
|
||||
/**
|
||||
* A class of local file sink nodes.
|
||||
*/
|
||||
class LocalFileSink extends DataFlow::Node {
|
||||
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) {
|
||||
filesystemInput(sink, _) or
|
||||
closesFile(sink, _)
|
||||
}
|
||||
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
|
||||
|
||||
@@ -44,10 +44,17 @@ class CookieSource extends DataFlow::Node {
|
||||
CookieSource() { this.asExpr() instanceof Cookie }
|
||||
}
|
||||
|
||||
/**
|
||||
* A class of cookie store sink nodes.
|
||||
*/
|
||||
class CookieStoreSink extends DataFlow::Node {
|
||||
CookieStoreSink() { cookieStore(this, _) }
|
||||
}
|
||||
|
||||
private module CookieToStoreFlowConfig implements DataFlow::ConfigSig {
|
||||
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>;
|
||||
|
||||
@@ -76,14 +76,21 @@ class SharedPreferencesEditorMethodCallSource extends DataFlow::Node {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class of shared preferences sink nodes.
|
||||
*/
|
||||
class SharedPreferencesSink extends DataFlow::Node {
|
||||
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) {
|
||||
sharedPreferencesInput(sink, _) or
|
||||
sharedPreferencesStore(sink, _)
|
||||
}
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof SharedPreferencesSink }
|
||||
}
|
||||
|
||||
private module SharedPreferencesFlow = DataFlow::Global<SharedPreferencesFlowConfig>;
|
||||
|
||||
@@ -4,15 +4,20 @@ import java
|
||||
private import semmle.code.java.dataflow.FlowSources
|
||||
private import semmle.code.java.StringFormat
|
||||
|
||||
/**
|
||||
* A class of string format sink nodes.
|
||||
*/
|
||||
class StringFormatSink extends DataFlow::Node {
|
||||
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
|
||||
|
||||
@@ -50,15 +50,22 @@ deprecated private class SensitiveResultReceiverConf extends TaintTracking::Conf
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class of sensitive result receiver sink nodes.
|
||||
*/
|
||||
class SensitiveResultReceiverSink extends DataFlow::Node {
|
||||
SensitiveResultReceiverSink() {
|
||||
exists(ResultReceiverSendCall call |
|
||||
untrustedResultReceiverSend(_, call) and
|
||||
this.asExpr() = call.getSentData()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private module SensitiveResultReceiverConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof SensitiveExpr }
|
||||
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
exists(ResultReceiverSendCall call |
|
||||
untrustedResultReceiverSend(_, call) and
|
||||
node.asExpr() = call.getSentData()
|
||||
)
|
||||
}
|
||||
predicate isSink(DataFlow::Node node) { node instanceof SensitiveResultReceiverSink }
|
||||
|
||||
predicate allowImplicitRead(DataFlow::Node n, DataFlow::ContentSet c) { isSink(n) and exists(c) }
|
||||
}
|
||||
|
||||
@@ -53,16 +53,23 @@ private class MaskCall extends MethodCall {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class of test field sink nodes.
|
||||
*/
|
||||
class TextFieldSink extends DataFlow::Node {
|
||||
TextFieldSink() {
|
||||
exists(SetTextCall call |
|
||||
this.asExpr() = call.getStringArgument() and
|
||||
not setTextCallIsMasked(call)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A configuration for tracking sensitive information to text fields. */
|
||||
private module TextFieldTrackingConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SensitiveExpr }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(SetTextCall call |
|
||||
sink.asExpr() = call.getStringArgument() and
|
||||
not setTextCallIsMasked(call)
|
||||
)
|
||||
}
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof TextFieldSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }
|
||||
|
||||
|
||||
@@ -153,6 +153,17 @@ module TempDirSystemGetPropertyToCreateConfig implements DataFlow::ConfigSig {
|
||||
module TempDirSystemGetPropertyToCreate =
|
||||
TaintTracking::Global<TempDirSystemGetPropertyToCreateConfig>;
|
||||
|
||||
/**
|
||||
* A class of method file directory creation sink nodes.
|
||||
*/
|
||||
class MethodFileDirectoryCreationSink extends DataFlow::Node {
|
||||
MethodFileDirectoryCreationSink() {
|
||||
exists(MethodCall ma | ma.getMethod() instanceof MethodFileDirectoryCreation |
|
||||
ma.getQualifier() = this.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration that tracks calls to to `mkdir` or `mkdirs` that are are directly on the temp directory system property.
|
||||
* Examples:
|
||||
@@ -172,11 +183,7 @@ module TempDirSystemGetPropertyDirectlyToMkdirConfig implements DataFlow::Config
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
exists(MethodCall ma | ma.getMethod() instanceof MethodFileDirectoryCreation |
|
||||
ma.getQualifier() = node.asExpr()
|
||||
)
|
||||
}
|
||||
predicate isSink(DataFlow::Node node) { node instanceof MethodFileDirectoryCreationSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node sanitizer) {
|
||||
isFileConstructorArgument(sanitizer.asExpr(), _, _)
|
||||
|
||||
@@ -44,18 +44,25 @@ deprecated class WebviewDebugEnabledConfig extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class of webview debug sink nodes.
|
||||
*/
|
||||
class WebviewDebugSink extends DataFlow::Node {
|
||||
WebviewDebugSink() {
|
||||
exists(MethodCall ma |
|
||||
ma.getMethod().hasQualifiedName("android.webkit", "WebView", "setWebContentsDebuggingEnabled") and
|
||||
this.asExpr() = ma.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A configuration to find instances of `setWebContentDebuggingEnabled` called with `true` values. */
|
||||
module WebviewDebugEnabledConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
node.asExpr().(BooleanLiteral).getBooleanValue() = true
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
exists(MethodCall ma |
|
||||
ma.getMethod().hasQualifiedName("android.webkit", "WebView", "setWebContentsDebuggingEnabled") and
|
||||
node.asExpr() = ma.getArgument(0)
|
||||
)
|
||||
}
|
||||
predicate isSink(DataFlow::Node node) { node instanceof WebviewDebugSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(Guard debug | isDebugCheck(debug) and debug.controls(node.asExpr().getBasicBlock(), _))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
private import java
|
||||
private import semmle.code.java.dataflow.ApiSources as ApiSources
|
||||
private import semmle.code.java.dataflow.ApiSinks as ApiSinks
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.FlowSources
|
||||
@@ -74,7 +75,7 @@ class ExternalApi extends Callable {
|
||||
|
||||
/** Holds if this API is a known sink. */
|
||||
pragma[nomagic]
|
||||
predicate isSink() { sinkNode(this.getAnInput(), _) }
|
||||
predicate isSink() { this.getAnInput() instanceof ApiSinks::SinkNode }
|
||||
|
||||
/** Holds if this API is a known neutral. */
|
||||
pragma[nomagic]
|
||||
|
||||
Reference in New Issue
Block a user