近期,在Google Play上架审核时审核失败,提示应用存有Implicit PendingIntent漏洞。
应用在上架前会先通过内部的一个预审工具平台先扫一遍,一切正常。
查看Google Play 政策更新也没更新,还停留在5月5日生效的政策,之前应用还是能正常过审的。
这就头疼了,看漏洞名,猜测了下是什么问题,Implicit PendingIntent,能想到的就是PendingIntent所使用的Intent,不明确指定启动哪个组件,而是设置Action、Data、Category,让系统来筛选出合适的组件。
下面是使用Google搜索验证了之后,看到的解决方案
大意就是:
- 确保设置 Intent的 action、package和component 字段
- 确保 PendingIntent 只传递给受信任的组件;
- 使用 FLAG_IMMUTABLE(在 SDK 23 中添加)创建 PendingIntent。这样可以阻止那些收到PendingIntent的应用填充未填充的属性。
是什么
虽然已经有了解决方案了,但还是需要了解下这个漏洞会造成的影响。
官方文档表示,PendingIntent使用隐式意图是一个安全漏洞,可能会导致拒绝服务、私人数据盗窃和特权升级。
拒绝服务这个就熟悉了,之前做安全审查的时候专门去研究过。可使用工具Intent Fuzzer检测。
Android应用本地拒绝服务漏洞主要是App没有对Intent.getXXXExtra()未做异常捕获处理,导致攻击者可能可以通过发送空数据或者异常数据导致App出现Crash。
android:exported属性为true的组件,都有可能被攻击。通常处理方案为:
-
将不必要的导出的组件设置为不导出,即
android:exported属性设置为false -
intent处理数据时进行捕获异常:
- 空指针异常;
- 类型转换异常;
- 数组越界访问异常;
- 类未定义异常;
- 其他异常;
在官方给出的包装隐式意图的 PendingIntent示例中:
// Create an implicit base Intent and wrap it in a PendingIntent
Intent base = new Intent("ACTION_FOO");
base.setPackage("some_package");
PendingIntent pi = PendingIntent.getService(this, 0, base, 0);
Intent设置了 ,android:exported将会默认为true,而且也未指定是哪个组件进行接收,这就有可能导致拒绝服务的风险。
在 Android 12 之前,有 intent-filter 属性的组件 (只有 Activity、Service 和 BroadcastReceiver) 自动被默认设定为 exported。
应用目标版本是 Android 12的话,系统会阻止这样的设置,并强制要求去设置 android:exported 属性。由于不想将 Activity 对外公开,可以设置 android:export=false,以确保应用的安全性。
怎么解决
采取的解决方案为 intent处理数据时进行捕获异常 + 设置ComponentName
Intent a = new Intent(packageContext,targetClass);
Intent b= new Intent();
b.setClassName(packageName,className);
Intent c = new Intent();
ComponentName componentName = new ComponentName(packageContext,targetClass);
c.setComponent(componentName)
这三种写法本质都是赋值给Intent里的mComponent(ComponentName)变量。
检测
第三方SDK中pushSDK里存在此漏洞的概率最高,目前只看了hms。
在最新的华为推送5.3.0.304版本中,已经修复此问题
如果要自检的话,推荐使用jadx反编译之后再全局搜索PendingIntent.getXXX,然后再查看相关的Intent是否有设置ComponentName,或写脚本利用apktool工具解压并遍历smali文件搜索相关特征代码进行自动化检索。