From f5ca459795491f86a68bbf950f32ec944cdc9704 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Thu, 25 Jun 2020 20:20:18 +0000 Subject: [PATCH] Add remote source of Android intent extra --- .../semmle/code/java/dataflow/FlowSources.qll | 34 +++++++++++++++++++ .../code/java/frameworks/android/Android.qll | 21 ++++++++++++ .../src/semmle/code/xml/AndroidManifest.qll | 5 +++ 3 files changed, 60 insertions(+) diff --git a/java/ql/src/semmle/code/java/dataflow/FlowSources.qll b/java/ql/src/semmle/code/java/dataflow/FlowSources.qll index fb2a0345b8b..253a39019a9 100644 --- a/java/ql/src/semmle/code/java/dataflow/FlowSources.qll +++ b/java/ql/src/semmle/code/java/dataflow/FlowSources.qll @@ -23,6 +23,7 @@ import semmle.code.java.frameworks.spring.SpringWebClient import semmle.code.java.frameworks.Guice import semmle.code.java.frameworks.struts.StrutsActions import semmle.code.java.frameworks.Thrift +import semmle.code.java.frameworks.android.Android /** A data flow source of remote user input. */ abstract class RemoteFlowSource extends DataFlow::Node { @@ -318,3 +319,36 @@ class AndroidIntentInput extends DataFlow::Node { ) } } + +/** + * Method access to external inputs of `android.content.Intent` object + */ +class IntentGetExtraMethodAccess extends MethodAccess { + IntentGetExtraMethodAccess() { + exists(AndroidComponent ac | + this.getEnclosingCallable().getDeclaringType() = ac and ac.isExported() + ) and + ( + this.getMethod().getName().regexpMatch("get\\w+Extra") and + this.getMethod().getDeclaringType() instanceof TypeIntent + or + this.getMethod().getName().regexpMatch("get\\w+") and + this.getQualifier().(MethodAccess).getMethod().hasName("getExtras") and + this.getQualifier().(MethodAccess).getMethod().getDeclaringType() instanceof TypeIntent + ) + } +} + +/** + * Android intent extra source + */ +private class AndroidIntentExtraSource extends RemoteFlowSource { + AndroidIntentExtraSource() { + exists(MethodAccess ma | + ma instanceof IntentGetExtraMethodAccess and + this.asExpr().(VarAccess).getVariable().getAnAssignedValue() = ma + ) + } + + override string getSourceType() { result = "Android intent extra" } +} diff --git a/java/ql/src/semmle/code/java/frameworks/android/Android.qll b/java/ql/src/semmle/code/java/frameworks/android/Android.qll index da500afbe6e..1415efedafd 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/Android.qll @@ -33,11 +33,25 @@ class AndroidComponent extends Class { /** An Android activity. */ class AndroidActivity extends AndroidComponent { AndroidActivity() { this.getASupertype*().hasQualifiedName("android.app", "Activity") } + + /** Holds if this Android component is configured as `exported` or has intent filters configured without `exported` explicitly disabled in an `AndroidManifest.xml` file. */ + override predicate isExported() { + getAndroidComponentXmlElement().isExported() + or + not getAndroidComponentXmlElement().isNotExported() and hasIntentFilter() + } } /** An Android service. */ class AndroidService extends AndroidComponent { AndroidService() { this.getASupertype*().hasQualifiedName("android.app", "Service") } + + /** Holds if this Android component is configured as `exported` or has intent filters configured without `exported` explicitly disabled in an `AndroidManifest.xml` file. */ + override predicate isExported() { + getAndroidComponentXmlElement().isExported() + or + not getAndroidComponentXmlElement().isNotExported() and hasIntentFilter() + } } /** An Android broadcast receiver. */ @@ -45,6 +59,13 @@ class AndroidBroadcastReceiver extends AndroidComponent { AndroidBroadcastReceiver() { this.getASupertype*().hasQualifiedName("android.content", "BroadcastReceiver") } + + /** Holds if this Android component is configured as `exported` or has intent filters configured without `exported` explicitly disabled in an `AndroidManifest.xml` file. */ + override predicate isExported() { + getAndroidComponentXmlElement().isExported() + or + not getAndroidComponentXmlElement().isNotExported() and hasIntentFilter() + } } /** An Android content provider. */ diff --git a/java/ql/src/semmle/code/xml/AndroidManifest.qll b/java/ql/src/semmle/code/xml/AndroidManifest.qll index 70afabc8d3d..7c6b2f3e569 100644 --- a/java/ql/src/semmle/code/xml/AndroidManifest.qll +++ b/java/ql/src/semmle/code/xml/AndroidManifest.qll @@ -137,6 +137,11 @@ class AndroidComponentXmlElement extends XMLElement { * Holds if the `android:exported` attribute of this component element is `true`. */ predicate isExported() { getExportedAttributeValue() = "true" } + + /** + * Holds if the `android:exported` attribute of this component element is explicitly set to `false`. + */ + predicate isNotExported() { getExportedAttributeValue() = "false" } } /**