1. 外部动态加载DEX文件风险描述

Android 系统提供了一种类加载器DexClassLoader,其可以在运行时动态加载并解释执行包含在JAR或APK文件内的DEX文件。外部动态加载DEX文件的安全风险源于:Anroid4.1之前的系统版本容许Android应用将动态加载的DEX文件存储在被其他应用任意读写的目录中(如sdcard),因此不能够保护应用免遭恶意代码的注入;所加载的DEX易被恶意应用所替换或者代码注入,如果没有对外部所加载的DEX文件做完整性校验,应用将会被恶意代码注入,从而执行的是恶意代码;
如果应用没有正确的动态加载DEX文件,将会导致攻击者的任意代码被自动执行,进一步实施欺诈、获取账号密码或其他恶意行为等危害,如在乌云漏洞平台上的类似漏洞:QQ游戏Android客户端漏洞导致任意代码执行和密码泄漏[1]。

2. 外部动态加载DEX文件影响范围

Android 系统

3.外部动态加载DEX文件风险详情

1) 风险位置:

 

 

2) 风险触发前提条件:

动态加载的DEX文件存储在被其他应用读写的目录中,如sdcard;
没有对外部所加载的DEX文件做完整性校验;

3) 风险原理:

动态加载的DEX文件存储在被其他应用人意读写的目录中(如sdcard),如果没有对外部所加载的DEX文件做完整性校验,应用将会被恶意代码注入,从而执行的是恶意代码;

4. 外部动态加载DEX文件风险证明

利用DexClassLoader()运行时加载JAR/DEX文件,该将恶意代码替换掉被加载的DEX文件,或向该被加载的DEX文件注入恶意代码。

被替换的所加载的JAR/DEX class的恶意代码如下:

动态加载JAR/DEX的调用代码:

Android 4.1之前系统版本,结果显示成功动态加载JAR/DEX如下图所示:

Android 4.1之后系统版本,结果抛出异常“Optimized data directory /mnt/sdcard is not owned by the current user. Shared storage cannot protect your application from code injection attacks.”:

由于4.1之后Android版本增加了对JAR/DEX存放目录文件的user_id 和动态加载JAR/DEX的进程的user_id是否一致的判断,如果不一致将抛出异常导致加载失败,如下图所示:
4.1之前版本的Android系统DexFile.java代码片段[3]:

4.1及其之后版本的Android系统DexFile.java代码片段[4]:

5. 外部动态加载DEX文件安全建议

1. 将所需要动态加载的DEX/APK文件放置在APK内部或应用私有目录中[5]

为了所加载的DEX/APK不被恶意代码注入,阿里聚安全建议将要动态加载的DEX/APK放置在APK内部;

2. 使用加密网络协议进行下载加载的DEX/APK文件并将其放置在应用私有目录中[5]

阿里聚安全建议使用加密网络协议进行下载并将下载的DEX或APK放置在应用的私有目录;

3. 对不可信的加载来源进行完整性校验

如果应用必须将所加载的DEX或APK放置在能被其他应用人意读写的目录中(如sdcard)或使用没有加密的网络协议进行下载加载源,阿里聚安全建议对这些不可信的加载源进行完整性校验和白名单处理,以保证不被恶意代码注入。