使用隐式 PendingIntents¶
ID: java/android/implicit-pendingintents
Kind: path-problem
Security severity: 8.2
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-927
Query suites:
- java-code-scanning.qls
- java-security-extended.qls
- java-security-and-quality.qls
PendingIntent
用于包装将在另一个应用程序中提供和执行的 Intent
。当 Intent
执行时,它的行为就好像是由提供应用程序直接运行的,使用该应用程序的权限。
如果 PendingIntent
配置为可变的,则接收应用程序可以更改其内部 Intent
的字段(前提是它们之前未设置)。这意味着,如果未定义目标组件(即隐式 PendingIntent
)的可变 PendingIntent
可以被更改以使用创建它的应用程序的权限执行任意操作。
恶意应用程序可以访问隐式 PendingIntent
,如下所示
它被包装并作为另一个隐式
Intent
的额外信息发送。它被发送为
Slide
的操作。它被发送为
Notification
的操作。
获得访问权限后,攻击者可以修改底层的 Intent
并使用提升的权限执行任意操作。这可能会让恶意应用程序访问受害者应用程序的私有组件,或者能够在没有必要权限的情况下执行操作。
建议¶
避免创建隐式 PendingIntent
。这意味着底层的 Intent
应该始终具有显式目标组件。
当您将 PendingIntent
作为另一个 Intent
的额外内容添加时,请确保此第二个 Intent
也具有显式目标组件,以防止它被传递到不受信任的应用程序。
尽可能使用标志 FLAG_IMMUTABLE
创建 PendingIntent
,以防止目标组件修改底层 Intent
的空字段。
示例¶
在以下示例中,创建了一个 PendingIntent
并将其包装为另一个 Intent
的额外内容。
在第一个示例中,PendingIntent
和其包装的 Intent
都是隐式的,使它们容易受到攻击。
在第二个示例中,通过向 PendingIntent
和包装的 Intent
添加显式目标组件,避免了这个问题。
第三个示例使用 FLAG_IMMUTABLE
标志来防止底层 Intent
被目标组件修改。
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
public class ImplicitPendingIntents extends Activity {
public void onCreate(Bundle savedInstance) {
{
// BAD: an implicit Intent is used to create a PendingIntent.
// The PendingIntent is then added to another implicit Intent
// and started.
Intent baseIntent = new Intent();
PendingIntent pi =
PendingIntent.getActivity(this, 0, baseIntent, PendingIntent.FLAG_ONE_SHOT);
Intent fwdIntent = new Intent("SOME_ACTION");
fwdIntent.putExtra("fwdIntent", pi);
sendBroadcast(fwdIntent);
}
{
// GOOD: both the PendingIntent and the wrapping Intent are explicit.
Intent safeIntent = new Intent(this, AnotherActivity.class);
PendingIntent pi =
PendingIntent.getActivity(this, 0, safeIntent, PendingIntent.FLAG_ONE_SHOT);
Intent fwdIntent = new Intent();
fwdIntent.setClassName("destination.package", "DestinationClass");
fwdIntent.putExtra("fwdIntent", pi);
startActivity(fwdIntent);
}
{
// GOOD: The PendingIntent is created with FLAG_IMMUTABLE.
Intent baseIntent = new Intent("SOME_ACTION");
PendingIntent pi =
PendingIntent.getActivity(this, 0, baseIntent, PendingIntent.FLAG_IMMUTABLE);
Intent fwdIntent = new Intent();
fwdIntent.setClassName("destination.package", "DestinationClass");
fwdIntent.putExtra("fwdIntent", pi);
startActivity(fwdIntent);
}
}
}
参考资料¶
Google 帮助:针对隐式 PendingIntent 漏洞的修复措施
常见弱点枚举:CWE-927.