Java: Identify more APIs as supported in the telemetry queries (as QL defined sources).

This commit is contained in:
Michael Nebel
2024-04-22 11:21:13 +02:00
parent 06f987ad58
commit acb2bbb2a3
11 changed files with 143 additions and 23 deletions

View File

@@ -0,0 +1,69 @@
/** Provides classes representing various flow sources for data flow / taint tracking. */
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.ExternalFlow
/**
* A data flow source node.
*/
abstract class SourceNode extends DataFlow::Node { }
/**
* 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 ApiSources {
private import FlowSources as FlowSources
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.ImplicitPendingIntentsQuery as ImplicitPendingIntentsQuery
private import semmle.code.java.security.ImproperIntentVerificationQuery as ImproperIntentVerificationQuery
private import semmle.code.java.security.InsecureTrustManager as InsecureTrustManager
private import semmle.code.java.security.JWT as Jwt
private import semmle.code.java.security.StackTraceExposureQuery as StackTraceExposureQuery
private import semmle.code.java.security.ZipSlipQuery as ZipSlipQuery
private class FlowSourcesSourceNode extends SourceNode instanceof FlowSources::SourceNode { }
private class ArbitraryApkInstallationSources extends SourceNode instanceof ArbitraryApkInstallation::ExternalApkSource
{ }
private class CleartextStorageAndroidDatabaseQuerySources extends SourceNode instanceof CleartextStorageAndroidDatabaseQuery::LocalDatabaseOpenMethodCallSource
{ }
private class CleartextStorageAndroidFilesystemQuerySources extends SourceNode instanceof CleartextStorageAndroidFilesystemQuery::LocalFileOpenCallSource
{ }
private class CleartextStorageCookieQuerySources extends SourceNode instanceof CleartextStorageCookieQuery::CookieSource
{ }
private class CleartextStorageSharedPrefsQuerySources extends SourceNode instanceof CleartextStorageSharedPrefsQuery::SharedPreferencesEditorMethodCallSource
{ }
private class ImplicitPendingIntentsQuerySources extends SourceNode instanceof ImplicitPendingIntentsQuery::ImplicitPendingIntentSource
{ }
private class ImproperIntentVerificationQuerySources extends SourceNode instanceof ImproperIntentVerificationQuery::VerifiedIntentConfigSource
{ }
private class InsecureTrustManagerSources extends SourceNode instanceof InsecureTrustManager::InsecureTrustManagerSource
{ }
private class JwtSources extends SourceNode instanceof Jwt::JwtParserWithInsecureParseSource { }
private class StackTraceExposureQuerySources extends SourceNode instanceof StackTraceExposureQuery::GetMessageFlowSource
{ }
private class ZipSlipQuerySources extends SourceNode instanceof ZipSlipQuery::ArchiveEntryNameMethodSource
{ }
/**
* Add all models as data sources.
*/
private class SourceNodeExternal extends SourceNode {
SourceNodeExternal() { sourceNode(this, _) }
}
}

View File

@@ -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" }
}

View File

@@ -96,10 +96,15 @@ private predicate localDatabaseStore(DataFlow::Node database, MethodCall store)
)
}
/**
* A class of local database open method call source nodes.
*/
class LocalDatabaseOpenMethodCallSource extends DataFlow::Node {
LocalDatabaseOpenMethodCallSource() { this.asExpr() instanceof LocalDatabaseOpenMethodCall }
}
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

View File

@@ -79,8 +79,15 @@ private class CloseFileMethod extends Method {
}
}
/**
* A class of local file open call source nodes.
*/
class LocalFileOpenCallSource extends DataFlow::Node {
LocalFileOpenCallSource() { this.asExpr() instanceof LocalFileOpenCall }
}
private module FilesystemFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof LocalFileOpenCall }
predicate isSource(DataFlow::Node src) { src instanceof LocalFileOpenCallSource }
predicate isSink(DataFlow::Node sink) {
filesystemInput(sink, _) or

View File

@@ -37,8 +37,15 @@ private predicate cookieStore(DataFlow::Node cookie, Expr store) {
)
}
/**
* A class of cookie source nodes.
*/
class CookieSource extends DataFlow::Node {
CookieSource() { this.asExpr() instanceof Cookie }
}
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, _) }
}

View File

@@ -67,11 +67,18 @@ private predicate sharedPreferencesStore(DataFlow::Node editor, MethodCall m) {
editor.asExpr() = m.getQualifier().getUnderlyingExpr()
}
/**
* A shared preferences editor method call source nodes.
*/
class SharedPreferencesEditorMethodCallSource extends DataFlow::Node {
SharedPreferencesEditorMethodCallSource() {
this.asExpr() instanceof SharedPreferencesEditorMethodCall
}
}
/** 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
}
predicate isSource(DataFlow::Node src) { src instanceof SharedPreferencesEditorMethodCallSource }
predicate isSink(DataFlow::Node sink) {
sharedPreferencesInput(sink, _) or

View File

@@ -13,11 +13,18 @@ private class OnReceiveMethod extends Method {
Parameter getIntentParameter() { result = this.getParameter(1) }
}
/**
* A class of verified intent source nodes.
*/
class VerifiedIntentConfigSource extends DataFlow::Node {
VerifiedIntentConfigSource() {
this.asParameter() = any(OnReceiveMethod orm).getIntentParameter()
}
}
/** A configuration to detect whether the `action` of an `Intent` is checked. */
private module VerifiedIntentConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
src.asParameter() = any(OnReceiveMethod orm).getIntentParameter()
}
predicate isSource(DataFlow::Node src) { src instanceof VerifiedIntentConfigSource }
predicate isSink(DataFlow::Node sink) {
exists(MethodCall ma |

View File

@@ -19,7 +19,7 @@ private class PrintStackTraceMethod extends Method {
}
private module ServletWriterSourceToPrintStackTraceMethodFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof XssVulnerableWriterSource }
predicate isSource(DataFlow::Node src) { src instanceof XssVulnerableWriterSourceNode }
predicate isSink(DataFlow::Node sink) {
exists(MethodCall ma |
@@ -95,7 +95,10 @@ predicate stringifiedStackFlowsExternally(DataFlow::Node externalExpr, Expr stac
)
}
private class GetMessageFlowSource extends DataFlow::Node {
/**
* A class of get message source nodes.
*/
class GetMessageFlowSource extends DataFlow::Node {
GetMessageFlowSource() {
exists(Method method | this.asExpr().(MethodCall).getMethod() = method |
method.hasName("getMessage") and

View File

@@ -62,7 +62,7 @@ private class DefaultXssSanitizer extends XssSanitizer {
/** A configuration that tracks data from a servlet writer to an output method. */
private module XssVulnerableWriterSourceToWritingMethodFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof XssVulnerableWriterSource }
predicate isSource(DataFlow::Node src) { src instanceof XssVulnerableWriterSourceNode }
predicate isSink(DataFlow::Node sink) {
exists(MethodCall ma |
@@ -105,6 +105,13 @@ class XssVulnerableWriterSource extends MethodCall {
}
}
/**
* A class of xss vulnerable writer source nodes.
*/
class XssVulnerableWriterSourceNode extends DataFlow::Node {
XssVulnerableWriterSourceNode() { this.asExpr() instanceof XssVulnerableWriterSource }
}
/**
* Holds if `s` is an HTTP Content-Type vulnerable to XSS.
*/

View File

@@ -21,13 +21,20 @@ private class ArchiveEntryNameMethod extends Method {
}
}
/**
* A class of entry name method source nodes.
*/
class ArchiveEntryNameMethodSource extends DataFlow::Node {
ArchiveEntryNameMethodSource() {
this.asExpr().(MethodCall).getMethod() instanceof ArchiveEntryNameMethod
}
}
/**
* A taint-tracking configuration for reasoning about unsafe zip file extraction.
*/
module ZipSlipConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(MethodCall).getMethod() instanceof ArchiveEntryNameMethod
}
predicate isSource(DataFlow::Node source) { source instanceof ArchiveEntryNameMethodSource }
predicate isSink(DataFlow::Node sink) { sink instanceof FileCreationSink }