2
2
3
3
import java .io .FileNotFoundException ;
4
4
import android .app .Activity ;
5
+ import android .app .Notification ;
6
+ import android .app .NotificationManager ;
5
7
import android .app .PendingIntent ;
8
+ import android .content .ComponentName ;
6
9
import android .content .Context ;
7
10
import android .content .Intent ;
8
11
import android .content .res .AssetFileDescriptor ;
19
22
20
23
public class ImplicitPendingIntentsTest {
21
24
22
- public static void test (Context ctx ) throws PendingIntent .CanceledException {
25
+ public static void testPendingIntentAsAnExtra (Context ctx )
26
+ throws PendingIntent .CanceledException {
23
27
{
24
28
Intent baseIntent = new Intent ();
25
29
PendingIntent pi = PendingIntent .getActivity (ctx , 0 , baseIntent , 0 );
@@ -34,6 +38,63 @@ public static void test(Context ctx) throws PendingIntent.CanceledException {
34
38
ctx .startActivity (fwdIntent ); // Safe
35
39
}
36
40
41
+ {
42
+ Intent baseIntent = new Intent ();
43
+ PendingIntent pi = PendingIntent .getActivityAsUser (ctx , 0 , baseIntent , 0 , null , null );
44
+ Intent fwdIntent = new Intent ();
45
+ fwdIntent .putExtra ("fwdIntent" , pi );
46
+ ctx .startActivity (fwdIntent ); // $hasTaintFlow
47
+ }
48
+
49
+ {
50
+ Intent baseIntent = new Intent ();
51
+ PendingIntent pi = PendingIntent .getActivities (ctx , 0 , new Intent [] {baseIntent }, 0 );
52
+ Intent fwdIntent = new Intent ();
53
+ fwdIntent .putExtra ("fwdIntent" , pi );
54
+ ctx .startActivity (fwdIntent ); // $hasTaintFlow
55
+ }
56
+
57
+ {
58
+ Intent baseIntent = new Intent ();
59
+ PendingIntent pi = PendingIntent .getActivitiesAsUser (ctx , 0 , new Intent [] {baseIntent },
60
+ 0 , null , null );
61
+ Intent fwdIntent = new Intent ();
62
+ fwdIntent .putExtra ("fwdIntent" , pi );
63
+ ctx .startActivity (fwdIntent ); // $hasTaintFlow
64
+ }
65
+
66
+ {
67
+ Intent baseIntent = new Intent ();
68
+ PendingIntent pi = PendingIntent .getBroadcast (ctx , 0 , baseIntent , 0 );
69
+ Intent fwdIntent = new Intent ();
70
+ fwdIntent .putExtra ("fwdIntent" , pi );
71
+ ctx .sendBroadcast (fwdIntent ); // $hasTaintFlow
72
+ }
73
+
74
+ {
75
+ Intent baseIntent = new Intent ();
76
+ PendingIntent pi = PendingIntent .getBroadcastAsUser (ctx , 0 , baseIntent , 0 , null );
77
+ Intent fwdIntent = new Intent ();
78
+ fwdIntent .putExtra ("fwdIntent" , pi );
79
+ ctx .sendBroadcast (fwdIntent ); // $hasTaintFlow
80
+ }
81
+
82
+ {
83
+ Intent baseIntent = new Intent ();
84
+ PendingIntent pi = PendingIntent .getService (ctx , 0 , baseIntent , 0 );
85
+ Intent fwdIntent = new Intent ();
86
+ fwdIntent .putExtra ("fwdIntent" , pi );
87
+ ctx .startActivity (fwdIntent ); // $hasTaintFlow
88
+ }
89
+
90
+ {
91
+ Intent baseIntent = new Intent ();
92
+ PendingIntent pi = PendingIntent .getForegroundService (ctx , 0 , baseIntent , 0 );
93
+ Intent fwdIntent = new Intent ();
94
+ fwdIntent .putExtra ("fwdIntent" , pi );
95
+ ctx .startActivity (fwdIntent ); // $hasTaintFlow
96
+ }
97
+
37
98
{
38
99
Intent safeIntent = new Intent (ctx , Activity .class ); // Sanitizer
39
100
PendingIntent pi = PendingIntent .getActivity (ctx , 0 , safeIntent , 0 );
@@ -85,6 +146,51 @@ public static void test(Context ctx) throws PendingIntent.CanceledException {
85
146
fwdIntent .putExtra ("fwdIntent" , pi );
86
147
ctx .startActivity (fwdIntent ); // $ SPURIOUS: $ hasTaintFlow
87
148
}
149
+ }
150
+
151
+ public static void testPendingIntentInANotification (Context ctx )
152
+ throws PendingIntent .CanceledException {
153
+
154
+ {
155
+ Intent baseIntent = new Intent ();
156
+ PendingIntent pi = PendingIntent .getActivity (ctx , 0 , baseIntent , 0 );
157
+ Notification .Action .Builder aBuilder = new Notification .Action .Builder (0 , "" , pi );
158
+ Notification .Builder nBuilder =
159
+ new Notification .Builder (ctx ).addAction (aBuilder .build ());
160
+ Notification notification = nBuilder .build ();
161
+ NotificationManager nManager = new NotificationManager ();
162
+ nManager .notifyAsPackage ("targetPackage" , "tag" , 0 , notification ); // $hasTaintFlow
163
+ nManager .notify (0 , notification ); // $hasTaintFlow
164
+ nManager .notifyAsUser ("" , 0 , notification , null ); // $hasTaintFlow
165
+ }
166
+ {
167
+ Intent baseIntent = new Intent ();
168
+ PendingIntent pi =
169
+ PendingIntent .getActivity (ctx , 0 , baseIntent , PendingIntent .FLAG_IMMUTABLE ); // Sanitizer
170
+ Notification .Action .Builder aBuilder = new Notification .Action .Builder (0 , "" , pi );
171
+ Notification .Builder nBuilder =
172
+ new Notification .Builder (ctx ).addAction (aBuilder .build ());
173
+ Notification notification = nBuilder .build ();
174
+ NotificationManager nManager = new NotificationManager ();
175
+ nManager .notify (0 , notification ); // Safe
176
+ }
177
+ {
178
+ // Even though pi1 is vulnerable, it's wrapped in fwdIntent,
179
+ // from which pi2 (safe) is created. Since only system apps can extract an Intent
180
+ // from a PendingIntent (via android.permission.GET_INTENT_SENDER_INTENT),
181
+ // the attacker has no way of accessing fwdIntent, and thus pi1.
182
+ Intent baseIntent = new Intent ();
183
+ PendingIntent pi1 = PendingIntent .getActivity (ctx , 0 , baseIntent , 0 );
184
+ Intent fwdIntent = new Intent ();
185
+ fwdIntent .putExtra ("fwdIntent" , pi1 );
186
+ PendingIntent pi2 =
187
+ PendingIntent .getActivity (ctx , 0 , fwdIntent , PendingIntent .FLAG_IMMUTABLE );
188
+ Notification .Action action = new Notification .Action (0 , "" , pi2 );
189
+ Notification .Builder nBuilder = new Notification .Builder (ctx ).addAction (action );
190
+ Notification notification = nBuilder .build ();
191
+ NotificationManager noMan = new NotificationManager ();
192
+ noMan .notify (0 , notification ); // Safe
193
+ }
88
194
89
195
}
90
196
0 commit comments