Skip to content

Commit 1eaa379

Browse files
authored
Merge pull request github#7681 from atorralba/atorralba/improve-android-implicit-intents-query
Java: Improvements to the Android query Use of implicit PendingIntents
2 parents 830c2dc + c7e1df5 commit 1eaa379

File tree

5 files changed

+59
-43
lines changed

5 files changed

+59
-43
lines changed

java/ql/lib/semmle/code/java/frameworks/android/Slice.qll

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,36 @@ private import semmle.code.java.dataflow.DataFlow
55
private import semmle.code.java.dataflow.FlowSteps
66
private import semmle.code.java.dataflow.ExternalFlow
77

8+
/** The class `androidx.slice.SliceProvider`. */
9+
class SliceProvider extends Class {
10+
SliceProvider() { this.hasQualifiedName("androidx.slice", "SliceProvider") }
11+
}
12+
13+
/**
14+
* An additional value step for modeling the lifecycle of a `SliceProvider`.
15+
* It connects the `PostUpdateNode` of any update done to the provider object in
16+
* `onCreateSliceProvider` to the instance parameter of `onBindSlice`.
17+
*/
18+
private class SliceProviderLifecycleStep extends AdditionalValueStep {
19+
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
20+
exists(Method onCreate, Method onBind, RefType declaringClass |
21+
declaringClass.getASupertype*() instanceof SliceProvider and
22+
onCreate.getDeclaringType() = declaringClass and
23+
onCreate.hasName("onCreateSliceProvider") and
24+
onBind.getDeclaringType() = declaringClass and
25+
onBind.hasName("onBindSlice")
26+
|
27+
node1
28+
.(DataFlow::PostUpdateNode)
29+
.getPreUpdateNode()
30+
.(DataFlow::InstanceAccessNode)
31+
.isOwnInstanceAccess() and
32+
node1.getEnclosingCallable() = onCreate and
33+
node2.(DataFlow::InstanceParameterNode).getEnclosingCallable() = onBind
34+
)
35+
}
36+
}
37+
838
private class SliceActionsInheritTaint extends DataFlow::SyntheticFieldContent,
939
TaintInheritingContent {
1040
SliceActionsInheritTaint() { this.getField().matches("androidx.slice.Slice.action") }

java/ql/lib/semmle/code/java/security/ImplicitPendingIntents.qll

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,7 @@ private class SendPendingIntent extends ImplicitPendingIntentSink {
6868
override predicate hasState(DataFlow::FlowState state) { state = "MutablePendingIntent" }
6969
}
7070

71-
/**
72-
* Propagates taint from any tainted object to reads from its `PendingIntent`-typed fields.
73-
*/
74-
private class PendingIntentAsFieldAdditionalTaintStep extends ImplicitPendingIntentAdditionalTaintStep {
75-
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
76-
exists(Field f |
77-
f.getType() instanceof PendingIntent and
78-
node1.(DataFlow::PostUpdateNode).getPreUpdateNode() =
79-
DataFlow::getFieldQualifier(f.getAnAccess().(FieldWrite)) and
80-
node2.asExpr().(FieldRead).getField() = f
81-
)
82-
}
83-
}
84-
85-
private class MutablePendingIntentFlowStep extends PendingIntentAsFieldAdditionalTaintStep {
71+
private class MutablePendingIntentFlowStep extends ImplicitPendingIntentAdditionalTaintStep {
8672
override predicate step(
8773
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
8874
DataFlow::FlowState state2

java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.qhelp

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,42 @@
55
<qhelp>
66

77
<overview>
8-
<p>A <code>PendingIntent</code> describes an action in the form of an Intent that is intended to be given and executed
9-
at a later time by another application. The Intent wrapped by a <code>PendingIntent</code> is executed on behalf of
10-
the application that created it, and with its same privileges.</p>
11-
<p>If a <code>PendingIntent</code> is configured to be mutable, the fields of its internal Intent can be changed by the
12-
receiving application if they were not previously set. This means that a mutable <code>PendingIntent</code> that has
13-
not defined a destination component (that is, an implicit <code>PendingIntent</code>) can be altered to execute an
8+
<p>A <code>PendingIntent</code> is used to wrap an <code>Intent</code> that will be supplied and executed by another
9+
application. When the <code>Intent</code> is executed, it behaves as if it were run directly by the supplying
10+
application, using the privileges of that application.</p>
11+
<p>If a <code>PendingIntent</code> is configured to be mutable, the fields of its internal <code>Intent</code> can be changed by the
12+
receiving application if they were not previously set. This means that a mutable <code>PendingIntent</code> that has
13+
not defined a destination component (that is, an implicit <code>PendingIntent</code>) can be altered to execute an
1414
arbitrary action with the privileges of the application that created it.</p>
15-
<p>If an implicit <code>PendingIntent</code> is obtainable by a malicious application by any of the following means:</p>
15+
<p>A malicious application can access an implicit <code>PendingIntent</code> as follows:</p>
1616
<ul>
17-
<li>It is wrapped and sent as an extra of another implicit Intent</li>
18-
<li>It is sent as the action of a Slide</li>
19-
<li>It is sent as the action of a Notification</li>
17+
<li>It is wrapped and sent as an extra of another implicit <code>Intent</code>.</li>
18+
<li>It is sent as the action of a <code>Slide</code>.</li>
19+
<li>It is sent as the action of a <code>Notification</code>.</li>
2020
</ul>
2121
<p></p>
22-
<p>the attacker could modify the underlying Intent and execute an arbitrary action with elevated privileges.
23-
This could give the malicious application access to private components of the victim application,
24-
or the ability to perform actions without having the necessary permissions.</p>
22+
<p>On gaining access, the attacker can modify the underlying <code>Intent</code> and execute an arbitrary action
23+
with elevated privileges. This could give the malicious application access to private components of the victim
24+
application, or the ability to perform actions without having the necessary permissions.</p>
2525
</overview>
2626

2727
<recommendation>
28-
<p>Avoid creating implicit <code>PendingIntent</code>s. This means that the underlying Intent should always have an
28+
<p>Avoid creating implicit <code>PendingIntent</code>s. This means that the underlying <code>Intent</code> should always have an
2929
explicit destination component.</p>
30-
<p>Also, when adding the <code>PendingIntent</code> as an extra of another Intent, make sure that said Intent also has
30+
<p>When you add the <code>PendingIntent</code> as an extra of another <code>Intent</code>, make sure that this second <code>Intent</code> also has
3131
an explicit destination component, so that it is not delivered to untrusted applications.</p>
32-
<p>It is also recommended to create the <code>PendingIntent</code> using the flag <code>FLAG_IMMUTABLE</code> whenever
33-
possible, to prevent the destination component from modifying empty fields of the underlying Intent.</p>
32+
<p>Create the <code>PendingIntent</code> using the flag <code>FLAG_IMMUTABLE</code> whenever possible,
33+
to prevent the destination component from modifying empty fields of the underlying <code>Intent</code>.</p>
3434
</recommendation>
3535

3636
<example>
37-
<p>In the following examples, a <code>PendingIntent</code> is created and wrapped as an extra of another Intent.
37+
<p>In the following examples, a <code>PendingIntent</code> is created and wrapped as an extra of another <code>Intent</code>.
3838
</p>
39-
<p>In the first example, both the <code>PendingIntent</code> and the Intent it is wrapped in are implicit,
40-
reproducing the vulnerability.</p>
39+
<p>In the first example, both the <code>PendingIntent</code> and the <code>Intent</code> it is wrapped in are implicit,
40+
making them vulnerable to attack.</p>
4141
<p>In the second example, the issue is avoided by adding explicit destination components to the
42-
<code>PendingIntent</code> and the wrapping Intent.</p>
43-
<p>The third example uses the <code>FLAG_IMMUTABLE</code> flag to prevent the underlying Intent from being modified
42+
<code>PendingIntent</code> and the wrapping <code>Intent</code>.</p>
43+
<p>The third example uses the <code>FLAG_IMMUTABLE</code> flag to prevent the underlying <code>Intent</code> from being modified
4444
by the destination component.</p>
4545
<sample src="ImplicitPendingIntents.java" />
4646
</example>

java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/**
22
* @name Use of implicit PendingIntents
3-
* @description Implicit and mutable PendingIntents being sent to an unspecified third party
4-
* component may provide access to internal components of the application or cause
5-
* other unintended effects.
3+
* @description Sending an implicit and mutable 'PendingIntent' to an unspecified third party
4+
* component may provide an attacker with access to internal components of the
5+
* application or cause other unintended effects.
66
* @kind path-problem
77
* @problem.severity error
88
* @security-severity 8.2

java/ql/src/change-notes/2021-12-21-android-implicit-pendingintents.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
category: newQuery
33
---
44
* A new query "Use of implicit PendingIntents" (`java/android/pending-intents`) has been added.
5-
This query finds implicit and mutable `PendingIntents` being sent to an unspecified third party component,
6-
which can provide access to internal components of the application or cause other unintended
7-
effects.
5+
This query finds implicit and mutable `PendingIntents` sent to an unspecified third party
6+
component, which may provide an attacker with access to internal components of the application
7+
or cause other unintended effects.

0 commit comments

Comments
 (0)