Android14应用安全措施

描述

一、前台服务类型

  targetSdkVersion 34 的情况下,必须为应用内的每个前台服务(foreground-services) 指定至少一种前台服务类型。

  前台服务类型是在Android10引入的,通过android:foregroundServiceType 可以指定 的服务类型,可供选择的前台服务类型有:

camera
connectedDevice
dataSync
health
location
mediaPlayback
mediaProjection
microphone
phoneCall
remoteMessaging
shortService
specialUse
systemExempted
 

     
二、Android14应用安全

1.对pending/implicit intent的限制

对于面向Android14的应用,Android通过以下方式限制应用向内部应用组件发送隐式intent:

(1).隐式intent仅传递给导出的组件,应用必须使用明确的intent来交付给未导出的组件,或者将组件标记为已导出(exported)。

(2).如果应用创建一个mutable pending intent,但intent未指定组件或包,系统现在会抛出异常。

  这些更改可防止恶意应用拦截只供给用内部组件使用的隐式intent,例如:


 

如果应用尝试使用隐式intent启动该 activity,则会抛出异常:

//Throws an exception when targeting Android 14.
context.startActivity(Intent("com.example.action.APP_ACTION"))

要启动未导出的Activity,应用应改用显式Intent:

//This makes the intent explicit.
val explicitIntent =
       Intent("com.example.action.APP_ACTION")
explicitIntent.apply {
   package = context.packageName
}
context.startActivity(explicitIntent)

2.运行时注册的广播接收器必须指定导出行为

  以Android14为目标,并使用context-registered

  receivers(ContextCompat.registerReceiver)应用和服务的需要指定一个标志,以指示接收器是否应导出到设备上的所有其他应用:分别为RECEIVER_EXPORTED或RECEIVER_NOT_EXPORTED。
 

val filter = IntentFilter(APP_SPECIFIC_BROADCAST)
val listenToBroadcastsFromOtherApps = false
val receiverFlags = if (listenToBroadcastsFromOtherApps) {
   ContextCompat.RECEIVER_EXPORTED
} else {
   ContextCompat.RECEIVER_NOT_EXPORTED
}
ContextCompat.registerReceiver(context, br, filter, receiverFlags)

3.仅接收系统广播的接收器例外

如果应用仅通过Context#registerReceiver方法为系统广播注册接收器时,那么它可以不在注册接收器时指定标志,例如 android.intent.action.AIRPLANE_MODE。  

4.更安全的动态代码加载

如果应用以Android14为目标平台并使用动态代码加载(DCL),则所有动态加载的文件都必须标记为只读,否则,系统会抛出异常。
 
建议应用尽可能避免动态加载代码,因为这样做会大大增加应用因代码注入或代码篡改而受到危害的风险。  

如果必须动态加载代码,请使用以下方法将动态加载的文件(例如:DEX、JAR或APK文件)在文件打开后和写入任何内容之前立即设置为只读:
 

val jar = File("DYNAMICALLY_LOADED_FILE.jar")
val os = FileOutputStream(jar)
os.use {
   // Set the file to read-only first to prevent race conditions
   jar.setReadOnly()
   // Then write the actual file content
}
val cl = PathClassLoader(jar, parentClassLoader)

5.处理已存在的动态加载文件

为防止现有动态加载文件抛出异常,我们建议可以尝试在应用中再次动态加载文件之前,删除并重新创建这些文件。

重新创建文件时,请按照前面的指导在写入时将文件标记为只读,或者将现有文件重新标记为只读,但在这种情况下,强烈建议首先验证文件的完整性(例如,通过根据可信值检查文件的签名),以帮助保护应用免受恶意操作。

6.Zip path traversal

对于针对Android14的应用,Android通过以下方式防止Zip路径遍历漏洞

如果zip文件条目名称包含".."或以"/"开头,则ZipFile(String)和ZipInputStream.getNextEntry()会抛出一个ZipException。

应用可以通过调用dalvik.system.ZipPathValidator.clearCallback()选择退出验证。

7.从后台启动活动的附加限制

针对Android14的应用,系统进一步限制了应用在后台启动Activity的时间

(1).当应用使用PendingIntent#send()发送PendingIntent以及类似行为时,如果应用想要授予其自己的后台service启动权限以启动pending intent,则该应用现在必须选择加入一个 ActivityOptions,具体为带有

setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
(2).当一个可见应用使用bindService()绑定另一个在后台运行的应用的服务时,如果该可见应用想要将其自己的后台activity启动权限授予绑定服务,则它现在必须选择加入 BIND_ALLOW_ACTIVITY_STARTS 标志。

这些更改扩展了现有的一组限制 ,通过防止恶意应用滥用 API 从后台启动破坏性活动来保护用户。  

8.Android14将禁止修改系统内置根证书

Android14不再允许开发者修改系统内置根证书进行调试,这意味着开发者无法通过诸如替换证书或中间人劫持的方式来检测某些流量。

  Android系统的证书存储库位于/system/etc/security/cacerts/,尽管从Android7.0开始开发者无法直接修改证书库,但如果root了那么还可以修改证书库路径,直接注入自己需要的证书,比如自签名的泛证书。  

而在Android14中,谷歌做了一项可以快速反应的安全措施:通过Google Play更新安卓系统的证书库。  

这样做也不是没有原因,以前证书绑定在系统里,谷歌无法直接更新,这导致有些证书被吊销后谷歌也无法及时操作,这也导致注入Let's Encrypt 因为需要兼容旧版安卓系统,不得不推迟证书更新,因为新证书不受旧版安卓系统的信任。 

后续谷歌可以随时通过Google Play更新证书库,包括加载新的ROOT CA和吊销某些ROOT CA,这让谷歌可以快速应对CA行业的某些问题。  

然而问题在于这种新的更新方法不再从/system/etc/security/cacerts/读取证书,而是从另一个路径/apex/com.android.conscrypt/cacerts/读取证书。  

而APEX容器背后确切的机制很难完全理解,因为存在很多细节没有公布出来,而在测试的时候开发者也发现尝试修改这个目录是没用的,系统会直接忽略修改。  

因此即便注入自签名的证书也无法被系统读取,所以也没法再使用中间人之类的手段进行劫持,来达到调试某些TLS流量的目的。  

好消息是Android14的这项变化有助于大幅度提高Android对CA行业的响应速度,例如快速吊销或信任证书,这将有助于提高Android设备的安全性。   ‍

坏消息就是对开发者和安全研究人员来说这就很难受了,因为无法让系统信任自签名证书,这将对调试和安全分析工作产生严重影响。

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分