Skip to content

Commit fd8a128

Browse files
committed
Renamed to AndroidIntentRedirection
Added qhelp
1 parent 09d96e6 commit fd8a128

10 files changed

+113
-78
lines changed

java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirect.qhelp

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
2+
<qhelp>
3+
<overview>
4+
<p>An exported Android component that obtains a user-provided Intent and uses it to launch another component
5+
can be exploited to obtain access to private, unexported components of the same app or to launch other apps' components
6+
in behalf of the victim app.</p>
7+
</overview>
8+
<recommendation>
9+
<p>Do not export compontents that start other components from a user-provided Intent.
10+
They can be made private by setting the `android:exported` property to `false` in the app's Android Manifest.</p>
11+
<p>If this is not possible, restrict either which apps can send Intents to the affected component, or which components can be started from it.</p>
12+
</recommendation>
13+
<example>
14+
<p>The following snippet contains two examples.
15+
In the first example, an arbitrary component can be started from the externally provided `forward_intent` Intent.
16+
In the second example, the destination component of the Intent is first checked to make sure it is safe.</p>
17+
<sample src="AndroidIntentRedirectionSample.java" />
18+
</example>
19+
<references>
20+
<li>
21+
Google:
22+
<a href="https://support.google.com/faqs/answer/9267555?hl=en">Remediation for Intent Redirection Vulnerability</a>.
23+
</li>
24+
<li>
25+
OWASP Mobile Security Testing Guide:
26+
<a href="https://mobile-security.gitbook.io/mobile-security-testing-guide/android-testing-guide/0x05a-platform-overview#intents">Intents</a>.
27+
</li>
28+
<li>
29+
Android Developers:
30+
<a href="https://developer.android.com/guide/topics/manifest/activity-element#exported">The `android:exported` attribute</a>.
31+
</li>
32+
</references>
33+
</qhelp>

java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirect.ql renamed to java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
/**
2-
* @name Android Intent redirect
3-
* @description xxx
2+
* @name Android Intent redirection
3+
* @description Starting Android components with user-provided Intents
4+
* can provide access to internal components of the application,
5+
* increasing the attack surface and potentially causing unintended effects.
46
* @kind path-problem
57
* @problem.severity error
6-
* @security-severity xx
8+
* @security-severity 7.5
79
* @precision high
8-
* @id java/android/unsafe-android-webview-fetch
10+
* @id java/android/intent-redirection
911
* @tags security
1012
* external/cwe/cwe-926
1113
* external/cwe/cwe-940
1214
*/
1315

1416
import java
1517
import semmle.code.java.dataflow.DataFlow
16-
import semmle.code.java.security.AndroidIntentRedirectQuery
18+
import semmle.code.java.security.AndroidIntentRedirectionQuery
1719
import DataFlow::PathGraph
1820

19-
from DataFlow::PathNode source, DataFlow::PathNode sink, IntentRedirectConfiguration conf
21+
from DataFlow::PathNode source, DataFlow::PathNode sink, IntentRedirectionConfiguration conf
2022
where conf.hasFlowPath(source, sink)
2123
select sink.getNode(), source, sink,
2224
"Arbitrary Android activities or services can be started from $@.", source.getNode(),
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// BAD: A user-provided Intent is used to launch an arbitrary component
2+
Intent forwardIntent = (Intent) getIntent().getParcelableExtra("forward_intent");
3+
startActivity(forwardIntent);
4+
5+
// GOOD: The destination component is checked before launching it
6+
Intent forwardIntent = (Intent) getIntent().getParcelableExtra("forward_intent");
7+
ComponentName destinationComponent = forwardIntent.resolveActivity(getPackageManager());
8+
if (destinationComponent.getPackageName().equals("safe.package") &&
9+
destinationComponent.getClassName().equals("SafeClass")) {
10+
startActivity(forwardIntent);
11+
}
12+
13+
// GOOD: The component that sent the Intent is checked before launching the destination component
14+
Intent forwardIntent = (Intent) getIntent().getParcelableExtra("forward_intent");
15+
ComponentName originComponent = getCallingActivity();
16+
if (originComponent.getPackageName().equals("trusted.package") && originComponent.getClassName("TrustedClass")) {
17+
startActivity(forwardIntent);
18+
}

java/ql/src/semmle/code/java/security/AndroidIntentRedirect.qll renamed to java/ql/src/semmle/code/java/security/AndroidIntentRedirection.qll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,26 @@ private import semmle.code.java.dataflow.DataFlow
55
private import semmle.code.java.frameworks.android.Intent
66

77
/**
8-
* A sink for Intent redirect vulnerabilities in Android,
8+
* A sink for Intent redirection vulnerabilities in Android,
99
* that is, method calls that start Android components (like activities or services).
1010
*/
11-
abstract class IntentRedirectSink extends DataFlow::Node { }
11+
abstract class IntentRedirectionSink extends DataFlow::Node { }
1212

1313
/** A sanitizer for data used to start an Android component. */
14-
abstract class IntentRedirectSanitizer extends DataFlow::Node { }
14+
abstract class IntentRedirectionSanitizer extends DataFlow::Node { }
1515

1616
/**
1717
* A unit class for adding additional taint steps.
1818
*
19-
* Extend this class to add additional taint steps that should apply to `IntentRedirectConfiguration`.
19+
* Extend this class to add additional taint steps that should apply to `IntentRedirectionConfiguration`.
2020
*/
21-
class IntentRedirectAdditionalTaintStep extends Unit {
21+
class IntentRedirectionAdditionalTaintStep extends Unit {
2222
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
2323
}
2424

25-
/** Default sink for Intent redirect vulnerabilities. */
26-
private class DefaultIntentRedirectSink extends IntentRedirectSink {
27-
DefaultIntentRedirectSink() {
25+
/** Default sink for Intent redirection vulnerabilities. */
26+
private class DefaultIntentRedirectionSink extends IntentRedirectionSink {
27+
DefaultIntentRedirectionSink() {
2828
exists(MethodAccess ma, Method m |
2929
ma.getMethod() = m and
3030
this.asExpr() = ma.getAnArgument() and
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
1-
/** Provides taint tracking configurations to be used in Android Intent Redirect queries. */
1+
/** Provides taint tracking configurations to be used in Android Intent redirection queries. */
22

33
import java
44
import semmle.code.java.dataflow.FlowSources
55
import semmle.code.java.dataflow.TaintTracking
6-
import semmle.code.java.security.AndroidIntentRedirect
6+
import semmle.code.java.security.AndroidIntentRedirection
77

88
/**
99
* A taint tracking configuration for user-provided Intents being used to start Android components.
1010
*/
11-
class IntentRedirectConfiguration extends TaintTracking::Configuration {
12-
IntentRedirectConfiguration() { this = "IntentRedirectConfiguration" }
11+
class IntentRedirectionConfiguration extends TaintTracking::Configuration {
12+
IntentRedirectionConfiguration() { this = "IntentRedirectionConfiguration" }
1313

1414
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
1515

16-
override predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectSink }
16+
override predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink }
1717

1818
override predicate isSanitizer(DataFlow::Node sanitizer) {
19-
sanitizer instanceof IntentRedirectSanitizer
19+
sanitizer instanceof IntentRedirectionSanitizer
2020
}
2121

2222
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
23-
any(IntentRedirectAdditionalTaintStep c).step(node1, node2)
23+
any(IntentRedirectionAdditionalTaintStep c).step(node1, node2)
2424
}
2525
}

java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectTest.java renamed to java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.java

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,50 +5,50 @@
55
import android.content.Intent;
66
import android.os.Bundle;
77

8-
public class AndroidIntentRedirectTest extends Activity {
9-
AndroidIntentRedirectTest(Context base) {
8+
public class AndroidIntentRedirectionTest extends Activity {
9+
AndroidIntentRedirectionTest(Context base) {
1010
super(base);
1111
}
1212

1313
public void onCreate(Bundle savedInstanceState) {
1414
{
1515
Intent intent = (Intent) getIntent().getParcelableExtra("forward_intent");
16-
startActivities(new Intent[] {intent}); // $ hasAndroidIntentRedirect
17-
startActivities(new Intent[] {intent}, null); // $ hasAndroidIntentRedirect
18-
startActivity(intent); // $ hasAndroidIntentRedirect
19-
startActivity(intent, null); // $ hasAndroidIntentRedirect
20-
startActivityAsUser(intent, null); // $ hasAndroidIntentRedirect
21-
startActivityAsUser(intent, null, null); // $ hasAndroidIntentRedirect
22-
startActivityAsCaller(intent, null, false, 0); // $ hasAndroidIntentRedirect
23-
startActivityAsUserFromFragment(null, intent, 0, null, null); // $ hasAndroidIntentRedirect
24-
startActivityForResult(intent, 0); // $ hasAndroidIntentRedirect
25-
startActivityForResult(intent, 0, null); // $ hasAndroidIntentRedirect
26-
startActivityForResult(null, intent, 0, null); // $ hasAndroidIntentRedirect
27-
startActivityForResultAsUser(intent, null, 0, null, null); // $ hasAndroidIntentRedirect
28-
startActivityForResultAsUser(intent, 0, null, null); // $ hasAndroidIntentRedirect
29-
startActivityForResultAsUser(intent, 0, null); // $ hasAndroidIntentRedirect
16+
startActivities(new Intent[] {intent}); // $ hasAndroidIntentRedirection
17+
startActivities(new Intent[] {intent}, null); // $ hasAndroidIntentRedirection
18+
startActivity(intent); // $ hasAndroidIntentRedirection
19+
startActivity(intent, null); // $ hasAndroidIntentRedirection
20+
startActivityAsUser(intent, null); // $ hasAndroidIntentRedirection
21+
startActivityAsUser(intent, null, null); // $ hasAndroidIntentRedirection
22+
startActivityAsCaller(intent, null, false, 0); // $ hasAndroidIntentRedirection
23+
startActivityAsUserFromFragment(null, intent, 0, null, null); // $ hasAndroidIntentRedirection
24+
startActivityForResult(intent, 0); // $ hasAndroidIntentRedirection
25+
startActivityForResult(intent, 0, null); // $ hasAndroidIntentRedirection
26+
startActivityForResult(null, intent, 0, null); // $ hasAndroidIntentRedirection
27+
startActivityForResultAsUser(intent, null, 0, null, null); // $ hasAndroidIntentRedirection
28+
startActivityForResultAsUser(intent, 0, null, null); // $ hasAndroidIntentRedirection
29+
startActivityForResultAsUser(intent, 0, null); // $ hasAndroidIntentRedirection
3030
}
3131
{
3232
Intent intent = (Intent) getIntent().getParcelableExtra("forward_intent");
33-
startService(intent); // $ hasAndroidIntentRedirect
34-
startServiceAsUser(intent, null); // $ hasAndroidIntentRedirect
33+
startService(intent); // $ hasAndroidIntentRedirection
34+
startServiceAsUser(intent, null); // $ hasAndroidIntentRedirection
3535
}
3636
{
3737
Intent intent = (Intent) getIntent().getParcelableExtra("forward_intent");
38-
sendBroadcast(intent); // $ hasAndroidIntentRedirect
39-
sendBroadcast(intent, null); // $ hasAndroidIntentRedirect
40-
sendBroadcast(intent, null, null); // $ hasAndroidIntentRedirect
41-
sendBroadcast(intent, null, 0); // $ hasAndroidIntentRedirect
42-
sendBroadcastAsUser(intent, null); // $ hasAndroidIntentRedirect
43-
sendBroadcastAsUser(intent, null, null); // $ hasAndroidIntentRedirect
44-
sendBroadcastAsUser(intent, null, null, null); // $ hasAndroidIntentRedirect
45-
sendBroadcastAsUser(intent, null, null, 0); // $ hasAndroidIntentRedirect
46-
sendBroadcastAsUserMultiplePermissions(intent, null, null); // $ hasAndroidIntentRedirect
47-
sendStickyBroadcast(intent); // $ hasAndroidIntentRedirect
48-
sendStickyBroadcastAsUser(intent, null); // $ hasAndroidIntentRedirect
49-
sendStickyBroadcastAsUser(intent, null, null); // $ hasAndroidIntentRedirect
50-
sendStickyOrderedBroadcast(intent, null, null, 0, null, null); // $ hasAndroidIntentRedirect
51-
sendStickyOrderedBroadcastAsUser(intent, null, null, null, 0, null, null); // $ hasAndroidIntentRedirect
38+
sendBroadcast(intent); // $ hasAndroidIntentRedirection
39+
sendBroadcast(intent, null); // $ hasAndroidIntentRedirection
40+
sendBroadcast(intent, null, null); // $ hasAndroidIntentRedirection
41+
sendBroadcast(intent, null, 0); // $ hasAndroidIntentRedirection
42+
sendBroadcastAsUser(intent, null); // $ hasAndroidIntentRedirection
43+
sendBroadcastAsUser(intent, null, null); // $ hasAndroidIntentRedirection
44+
sendBroadcastAsUser(intent, null, null, null); // $ hasAndroidIntentRedirection
45+
sendBroadcastAsUser(intent, null, null, 0); // $ hasAndroidIntentRedirection
46+
sendBroadcastAsUserMultiplePermissions(intent, null, null); // $ hasAndroidIntentRedirection
47+
sendStickyBroadcast(intent); // $ hasAndroidIntentRedirection
48+
sendStickyBroadcastAsUser(intent, null); // $ hasAndroidIntentRedirection
49+
sendStickyBroadcastAsUser(intent, null, null); // $ hasAndroidIntentRedirection
50+
sendStickyOrderedBroadcast(intent, null, null, 0, null, null); // $ hasAndroidIntentRedirection
51+
sendStickyOrderedBroadcastAsUser(intent, null, null, null, 0, null, null); // $ hasAndroidIntentRedirection
5252
}
5353

5454
}

java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectTest.ql renamed to java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import java
2-
import semmle.code.java.security.AndroidIntentRedirectQuery
2+
import semmle.code.java.security.AndroidIntentRedirectionQuery
33
import TestUtilities.InlineExpectationsTest
44

5-
class HasAndroidIntentRedirectTest extends InlineExpectationsTest {
6-
HasAndroidIntentRedirectTest() { this = "HasAndroidIntentRedirectTest" }
5+
class HasAndroidIntentRedirectionTest extends InlineExpectationsTest {
6+
HasAndroidIntentRedirectionTest() { this = "HasAndroidIntentRedirectionTest" }
77

8-
override string getARelevantTag() { result = "hasAndroidIntentRedirect" }
8+
override string getARelevantTag() { result = "hasAndroidIntentRedirection" }
99

1010
override predicate hasActualResult(Location location, string element, string tag, string value) {
11-
tag = "hasAndroidIntentRedirect" and
12-
exists(DataFlow::Node src, DataFlow::Node sink, IntentRedirectConfiguration conf |
11+
tag = "hasAndroidIntentRedirection" and
12+
exists(DataFlow::Node src, DataFlow::Node sink, IntentRedirectionConfiguration conf |
1313
conf.hasFlow(src, sink)
1414
|
1515
sink.getLocation() = location and

java/ql/test/query-tests/security/CWE-940/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
android:label="@string/app_name"
1010
android:theme="@style/AppTheme" >
1111
<activity
12-
android:name=".AndroidIntentRedirectTest"
12+
android:name=".AndroidIntentRedirectionTest"
1313
android:icon="@drawable/ic_launcher"
1414
android:label="@string/app_name">
1515
<intent-filter>

0 commit comments

Comments
 (0)