Android 12 已来,你的 App 崩溃了吗?我们已经开始做 Android 12 的适配了,在 Android 12 中包含了很多的功能和一些行为的变更,接下来我们一起来分析这些行为的变更对我们的应用产生了那些影响。
通过这篇文章你将学习到以下内容:
- 为什么在 Android 12 上需要显示声明 android:exported 属性?
- 为什么在 Android 12 上需要显示指定 PendingIntent 的可变性?
- 为什么在 Android 12 上限制 adb 备份的默认行为?
- 如何检查 App 的安全漏洞?
android:exported 属性
在 Android 12 中包含 的 activity 、 service 或 receiver必须为这些应用组件显示声明 android:exported 属性,如下所示。
- <activity
- android:name=".TestActivity"
- android:exported="false">
- <intent-filter>
- ......
- </intent-filter>
- </activity>
如果在包含 的 activity 、 service 或 receiver 组件中,没有显示声明 android:exported 的值,你的应用将无法安装,错误日志如下所示。
- Installation did not succeed.
- The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE
- List of apks:
- [0] '.../build/outputs/apk/debug/app-debug.apk'
- Installation failed due to: 'null'
如果您的应用在需要声明 android:exported 的值时未进行此声明,错误日志如下所示。
- Targeting S+ (version 10000 and above) requires that an explicit value for \
- android:exported be defined when intent filters are present
如果对上面的异常产生的条件,不是很理解,可以点击下方链接查看,目前已经有很多开源项目都已经开始适配这个行为的变更了,例如 leakcanary 等等。
这个行为的变更无论是对库开发者 和 还是应用开发者影响都非常大。
为什么在 Android 12 上需要显示声明 android:exported 属性
android:exported 属性的默认值取决于是否包含 ,如果包含 那么默认值为 true,否则 false。
- 当 android:exported="true" 时,如果不做任何处理,可以接受来自其他 App 的访问
- 当 android:exported="false" 时,限制为只接受来自同一个 App 或一个具有相同 user ID 的 App 的访问
正因为 android:exported 的属性的默认值的问题,Twicca App 发生过一次安全性问题,因为另一个没有访问 SD 卡或网络权限的 App,可以通过 Twicca App 将存储在 SD 卡上的图片或电影上传到 Twicca 用户的 Twitter 账户上的社交网络上。
产生问题的代码如下所示:
- <activity android:configChanges="keyboard|keyboardHidden|orientation" android:name=".media.yfrog.YfrogUploadDialog" android:theme="@style/Vulnerable.Dialog" android:windowSoftInputMode="stateAlwaysHidden">
- <intent-filter android:icon="@drawable/yfrog_icon" android:label="@string/YFROG">
- <action android:name="jp.co.vulnerable.ACTION_UPLOAD" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="image/*" />
- <data android:mimeType="video/*" />
- </intent-filter>
- </activity>
因为添加了 intent-filter 所以 android:exported 的属性的默认值为 true,因此可以接受来自其他 App 的访问,进而造成了上述问题(通过 Twicca App 将存储在 SD 卡上的图片或电影上传到 Twicca 用户的 Twitter 账户上的社交网络上),而解决方案有两个:
方案一:添加 android:exported="false" 属性
- <activity android:exported="false" android:configChanges="keyboard|keyboardHidden|orientation" android:name=".media.yfrog.YfrogUploadDialog" android:theme="@style/ VulnerableTheme.Dialog" android:windowSoftInputMode="stateAlwaysHidden" >
- </activity>
方案二:Twicca App 没有使用方式一,而是检查调用者的包名是否与自身的包名相同
- public void onCreate(Bundle arg5) {
- super.onCreate(arg5);
- ...
- ComponentName v0 = this.getCallingActivity();
- if(v0 == null) {
- this.finish();
- } else if(!jp.r246.twicca.equals(v0.getPackageName())) {
- this.finish();
- } else {
- this.a = this.getIntent().getData();
- if(this.a == null) {
- this.finish();
- }
- ...
- }
- }
- }
这种方案也是可行的,因为在一台设备上,不可能会出现两个包名相同的应用。
这仅仅是关于 activity 的安全漏洞的其中一个,在不同的场景下利用这些漏洞做的事情也可能不一样。当然还有 service 和 receiver 组件也都是一样,存在安全性问题。
指定 PendingIntent 的可变性
在 Android 12 中创建 PendingIntent 的时候,需要显示的声明是否可变,请分别使用 PendingIntent.FLAG_MUTABLE 或 PendingIntent.FLAG_IMMUTABLE 标志,如果您的应用试图在不设置任何可变标志的情况下创建 PendingIntent 对象,系统会抛出 IllegalArgumentException 异常,错误日志如下所示。
- PACKAGE_NAME: Targeting S+ (version 10000 and above) requires that one of \
- FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
- Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
- some functionality depends on the PendingIntent being mutable, e.g. if \
- it needs to be used with inline replies or bubbles.
为什么在 Android 12 上需要显示的指定 PendingIntent 的可变性
在 Adnroid 12 之前,默认创建一个 PendingIntent 它是可变的,因此其他恶意应用程序可能会拦截,重定向或修改此 Intent。(但是是有条件限制的)
一个 PendingIntent 是一个可以给另一个应用程序使用的 Intent,PendingIntent 接收待处理意图的应用程序可以使用与产生待处理意图的应用程序相同的权限和身份执行待处理意图中指定的操作。
因此,创建待处理意图时必须小心,为了安全性 Google 在 Android 12 中需要开发者自己来指定 PendingIntent 的可变性。
adb 备份限制
Android 开发者都应该知道这个命令 adb backup , 它可以备份应用的数据,在 Android 12 中,为了保护私有应用数据,用户运行 adb backup 命令时,从设备导出的任何其他系统数据都不包含应用数据。
如果你在测试和开发过程中需要使用 adb backup 来备份应用数据,你可以在 AndroidManifest 中将 android:debuggable 设置为 true 来导出应用数据。
- <application
- android:name=".App"
- android:debuggable="true"
- ....../>
注意:在发布应用前将 android:debuggable 设置为 false。
为什么在 Android 12 上限制了 adb backup 命令的默认行为
因为这个存在严重的安全问题,当初 Google 为了提供 App 数据备份和恢复功能,可以在 AndroidManifest 中添加 android:allowBackup 属性,默认值为 true, 当你创建一个应用的时候,会默认添加这个属性,如下所示。
- <application
- android:name=".App"
- android:allowBackup="true"
- ....../>
当 android:allowBackup="true" 时,用户可以通过 adb backup 和 adb restore命令对应用数据进行备份和恢复,也就是说可以在其他的 Android 手机上安装同一个应用,通过如上命令恢复用户的数据。
为了安全起见,我们在发布出去的 Apk 中一定要将 android:allowBackup 属性设置为 false 来关闭应用程序的备份和恢复功能,以免造成信息泄露。国民级应用 XX 信, 在曾今发出的版本中 allowBackup 的属性值是 true,被其他逆向开发者利用之后,现在的版本中这个值已经修改为 false了,有兴趣的小伙们可以反编译看看。
如何检查 App 的安全漏洞
在这里推荐一个开源项目 linkedin/qark 这是由 LinkedIn 开源的项目,这个工具被设计用来寻找与安全相关的 Android 应用程序漏洞,无论是源代码还是打包的 APK,具体的用法文档上写的非常的清楚了,这里不做详细的介绍了。
当然也有很多公司花了重金去购买第三方的服务来检查 App 的安全漏洞。
在 Android 12 上这几个行为的变更它们都有一个共性:安全性,可见 Google 这几年在安全上做了很多的努力,当然还有其他的一些行为的变更,可以前往查看 行为变更:以 Android 12 为目标平台的应用。
https://developer.android.com/about/versions/12/behavior-changes-12
最后
在这里还分享一份由大佬亲自收录整理的学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料
这些都是我现在闲暇时还会反复翻阅的精品资料。里面对近几年的大厂面试高频知识点都有详细的讲解。相信可以有效地帮助大家掌握知识、理解原理,帮助大家在未来取得一份不错的答卷。
当然,你也可以拿去查漏补缺,提升自身的竞争力。