Android 常见安全漏洞修复理论与实践

前言

前段时间公司对应用在爱加密上进行了安全扫描,本文将基于爱加密的漏洞分析报告,针对部分内容,介绍理论修复实践

最小化特权准则概念介绍

最小化特权准则,即指组件只能供自身应用调用,尽可能禁止其他应用访问及调用。

违反最小化特权的危害

若组件违反最小化特权准则,则会带来如下危害:

  1. 攻击者恶意调用应用的 Activity, 修改程序的状态或关键数据。举个例子,如果您的应用的应用需要人脸认证才可以登录,一般需要保存一个人脸认证状态,如果攻击者修改了人脸状态,改为已认证通过,则可以直接进入应用主页。

  2. 通过调用 Activity 内部的方法,可获取私密数据,甚至造成拒绝服务和应用崩溃。例如,如果您的登录 Activity 违反了最小化特权准则,攻击装者可通过反射,来调用您的 Activity 有一个私有方法,用来获取账号和密码。

解决方案

  1. 设置 Activity 组件 android:exported = false
  2. 必须 exported 的 Activity 组件必须仅限于授权用户或者特定组件调用
  3. 谨慎使用 intent-filter 属性,若必须使用,则需强制设置 android:exported = false

这里涉及几个概念,简要介绍一下:

1. android:exported

适用于 Android 四大组件,其作用是控制其他应用程序是否可以与当前组件交互。其中 true 为可以与之交互。若设置为 false ,意味着对于 Service 组件,只有相同应用程序的组件或相同用户 ID 的程序才能启动或绑定该服务。值得注意的是,如果该组件在 AndroidManifest 中声明了 intent-filter , 该组件的 exported 属性将自动设置为 true。若没有声明,则默认为 false.

2. 用户 ID (UID)

对于 Android 应用,每个应用程序都有一个 UID, 默认情况下,Android 系统会为每一个分配一个互不相同的 UID. 如果两个应用的 UID 不同,则不能相互调用。若希望相互调用,可进行如下操作:

  1. 设置 android:sharedUserId 属性,该属性的作用是将一个或多个应用程序共享同一个 UID。具体代码如下所示:
  2. 两个应用需使用相同的签名文件进行签名
// 应用一


// 应用二


3. 自定义安全权限

该标签用于在 AndroidManifest 中声明一个安全权限,可用于此应用程序的特定组件或功能的访问。例如一个发送广播的业务,APK1 用于接收广播,APK2 用于发送广播,APK1 此时仅想接收声明了对应权限的应用发送的广播。此时需要在 APK1 通过 定义安全权限, 在 APK2 通过 申请 APK1 定义的安全权限即可。 定义格式如下:

 

  • android:description 用于描述该权限所针对的操作及用户授予这个权限的后果
  • android:label 用于描述该权限
  • android:name 用于唯一标识权限
  • android:permissionGroup 用于标识该权限所属权限组的名称
  • android:protectionLevel 用于标识该权限的等级,可控制权限的授予方式,normal 表示声明后自动获取,signature 表示定义权限的 APK 和声明权限的 APK 必须使用同一签名文件,才可获取权限。

Activity 最小化特权漏洞修复

案例详解 1

在本例中,IncomingDialog 为会议振铃和外呼界面。由于 IncomingDialog 设置了 标签 导致了android:exported = true, 因此,强制设置 exported 为 false 即可
修改前:

        
            
                

                
            
        

修改后:

 
            
                

                
            
        

这里简要介绍一下 android:enabled 属性,该属性适用于四大组件,控制该组件是否可以被系统初始化,默认为 true, 如果设置为 false, 对应控件无法初始化,例如无法启动服务。值得注意的是, 标签中也会可以声明该属性,而且该 enabled 与 组件声明都为 true 的情况下组件才可被初始化。修改点同样是将 exported 改为 false

数据越权备份风险

概念

应用数据备份

Android 2.1 系统可为 APP 提供数据的备份与恢复功能,可在 AndroidManifest 标签下声明 android:allowBackup, 属性决定是否禁用该功能,其中 false 标识禁用。值得注意的是该属性默认为 true

违反数据越权备份的危害

攻击者可利用此漏洞攻击任何可以打开 USB 调试的应用非 root 设备。

  1. 通过 adb backup 命令,将制定应用的数据拷贝到外设。一旦该应用数据被备份后,所有的用户在这个应用的SharedPreferencesDB都可被攻击者读取。
  2. 通过 adb restore 命令,可指定某个备份数据,恢复应用的数据

虽然可以对备份后的文件(.ab)进行加密,但是仍有许多工具工具可对其解密,例如: android-backup-extractor, 下面将简单介绍一下 adb backup 的用法

adb backup

adb backup [-system|-nosystem] -all [-apk|-noapk] [-shared|-noshared] -f <档案名称> [需要备份的应用包名]

例如想备份包名为emergency.cicdi.com的数据,可以输入如下代码:

adb backup -nosystem -noapk -f emergency.ab emergency.cicdi.com

该命令会在当前目录下生成名为 emergency.ab 的备份文件。通过 android-backup-extractor ,可得到对应应用的SharedPreferencesDB文件

解决方案

将 app module 下的 AndroidManifest.xml 中设置 android:allowBackup="false" 即可,但是这么处理是不够的,会遇到一个问题,由于我们的项目集成了多个依赖,比如扫码二维码的库,和 IM Library, 依赖中 AndroidManifest 都默认设置 android:allowBackup="true" ,会导致编译时不同 module 合并 AndroidManifest 文件会产生冲突。需要解决冲突,即统一该属性的取值。但是有些 library 是远程依赖,本地项目并不可以编辑代码,而且一个一个修改未免效率较低,因此需要在 app module 下的 AndroidManifest.xml 中声明

    
        ...

这行代码标识 Manifest 合并规则,意味着当合并 library 中的 Manifest 文件到主 App Manifest时,不考虑 library Manifest 中的 allowBackup 取值,以 app 中的 Manifest 为准进行合并。

你可能感兴趣的:(Android 常见安全漏洞修复理论与实践)