王嘉捷, 刘建鑫,, 马宇飞, 邵帅, 张普含
(1. 中国信息安全测评中心 北京 100085; 2. 中国科学技术大学 安徽,合肥 230026)
WebView组件为Android应用提供网络视图显示等功能,有效提高了交互性,被开发者广泛使用. 然而,由于设计缺陷、编程失误等原因,操作WebView不当将产生严重的安全问题,如著名的WebView组件远程代码执行漏洞CVE-2014-1939.
目前,WebView组件漏洞检测主要依赖于对WebView危险操作等敏感函数的匹配识别. 该方法误报率较高,因为Android应用常因内嵌多个第三方代码库等原因而存在大量无用的死代码,若匹配识别到死代码段中的敏感函数,则往往因难以触发而产生误报. 同时,WebView组件漏洞的触发需要有效控制涉及敏感函数的网络流量,使得攻击者构造的输入数据能够达到相关漏洞代码,因此单纯匹配识别敏感函数而忽略网络输入与执行路径,将产生大量漏洞误报.
Enck等[1]对Android应用在Android虚拟机Dalvik上的编码方式进行了深入研究,率先将Dalvik字节码反编译成Java字节码,进而提高对Android应用安全问题的检测能力. 此后大量Android应用检测工具开始出现. Chin等[2]以反编译结果为基础,静态分析检测Intent通信过程是否存在服务劫持等漏洞. Arzt等[3]研究并实现一种精确的静态污点传播分析工具FlowDroid,通过建立数据流图检测隐私数据泄露问题. 静态分析程序Appintent[4]、PiOS[5]可以全面检查应用的数据流动并展示数据泄露问题的代码路径. 但静态分析通常对时间、存储消耗很大,且易产生误报. TaintDroid[6]通过动态污点传播分析,对用户隐私信息泄露问题进行检测. 动态污点分析在实际运行路径中分析,因此结果更为准确,但运行时的高昂开销限制了其应用. Xia等[7]提出了一种基于静态分析与动态分析相结合的应用审计框架AppAudit,静态分析时仅做粗略判断,而后动态分析时,利用近似执行的方法,对未知变量进行有效猜测,以保证分析路径尽可能覆盖完整,用以发现数据泄露漏洞. Chin等[8]利用静态分析方式对WebView File域同源策略绕过漏洞进行检测,主要分析URL地址是否可以指向恶意网站,使用户终端加载恶意Javascript,造成隐私泄露. 叶嘉羲等[9]设计了一种静态分析与动态分析相结合的检测方法,对WebView组件远程代码执行漏洞进行检测,但该方式的静态分析为粗粒度检测,无法解决addJavascriptInterface函数参数外部传入等问题,检测能力不足.
针对WebView组件漏洞的系统性研究目前较少,检测程度不深,且多数检测方法只依赖静态分析或动态分析的单一技术. 由于两种方法使用技术差异,静态分析结果漏报率较低,但误报率较高;动态分析结果较为可靠,但易产生漏报. 因此,使用单一技术难以满足高效可靠的检测要求,也不易提高自动化程度,往往需要人工进行二次确认.
为了降低误报率,本文分析了WebView组件漏洞的产生条件与现有检测方式的不足,提出了一种以静态分析,指导动态验证的自动化检测与验证方法(automated detection and verification method,ADV). 静态分析主要负责细粒度地发现可疑点,保留了静态匹配漏报率低的优势,同时通过对应用建立全路径的过程间控制流图,对可疑漏洞点进行代码可达性分析,避免因死代码情况产生的误报;通过动态验证,模拟网络流量真实攻击情况,自动触发并判断漏洞可疑点的真实性. 两种检测方式有机结合,确保了检测结果的可靠性,降低了漏洞误报率.
WebView组件漏洞通常需要通过执行恶意html页面来触发,所以攻击者也将攻击面集中在可以修改的html页面上或可加载攻击者控制的带html页面的功能上.
① 篡改网络流量:这是一种最常见的触发WebView组件漏洞的攻击方式. 攻击者通过建立中间路由、WiFi信号覆盖等方式实现对网络流量的监听与篡改. 攻击者常以提供免费WiFi上网形式,在被攻击对象毫不知情的情况下实现对流量篡改. 被攻击对象因被免费上网所诱惑,往往主动接入WiFi,致使这种方式成功率较高.
② 传入特定html页面:这种攻击需要特定的条件才能发生,即依赖于可以传入特定html页面的接口. 这听起来比较困难,但实际情况却较为容易. 例如,经常被忽略安全风险的扫二维码功能. 目前许多应用都提供扫二维码功能,一旦这些应用存在WebView漏洞,攻击者即可构造恶意html页面,生成链接二维码,诱导被攻击对象通过扫二维码功能以传入恶意html页面. 这种情况尤其在商城类应用或提供交易性质功能的应用中发生比例较高.
③ 利用其他应用伪装:这是一种非常隐蔽的攻击方式. 攻击者将攻击行为伪装在提供其他便捷功能的应用中,诱导被攻击对象安装这些恶意应用. 完成安装后,被攻击对象本以为在使用其他功能,却早已被攻击者攻陷. 表面上看,这种攻击方式需要诱导被攻击对象安装这些恶意应用,是极为困难的. 但实际上,第三方应用市场存在着大量的未经检查的应用,普通用户很难判断应用的安全性,仅依靠功能需求进行下载. 因此,攻击者只需设计合理的伪装功能,即可诱导大量普通用户安装,甚至减少攻击所需的权限要求. 例如,某些第三方阅读助手、辅助盒子、辅助工具、强行代理工具、某些hook插件等,其功能实现上即需要获取原始应用的网络流量等信息,因此用户在被诱导安装这些恶意应用时,还极易被诱导安装这些恶意应用的代理证书,进而带来更大安全问题.
通过对WebView组件漏洞的威胁模型分析,可以发现,攻击者要成功利用WebView组件漏洞,至少需要两个条件:应用不安全地使用了WebView组件、攻击者有一定的html页面控制能力.
目前常见的针对WebView组件漏洞的检测方式是依赖对敏感函数的静态匹配. 例如,匹配所有使用了addJavascriptInterface函数的地方,认为存在远程代码执行漏洞. 这种检测方式依靠模式匹配的细致化,很难产生漏报,但容易产生误报. 产生误报的原因主要有:
① 存在敏感函数的WebView组件未在实际运行中被调用. 这种情况极为常见,目前Android应用开发迭代速度较快且模块化程度高,开发人员很难细致地审查代码的精简程度与相互之间的严谨性,往往将相似功能以库形式存储,开发时调用各种库的部分功能,以完成产品的快速开发. 因此,Android应用中存在着许多死代码的情况,即使其中存在addJavascriptInterface等敏感函数,但因其是死代码,故并非真实漏洞.
② 攻击者无法控制html页面. 设计良好的https传输可以防止攻击者对网络流量的篡改,同时没有其他入口传入html页面,设计必要的防流量监听功能,多次进行完整性或其他方面的校验等方式,能够使攻击者无法控制html页面,进而无法触发WebView组件漏洞,即不存在安全问题.
为了解决目前检测方式容易产生误报的问题,本文设计了检测方法XWebView,方法框架图如图1所示,既保留静态分析漏报率低的特点,又通过可达性分析、动态验证等方式来降低误报率,确保检测结果的真实可靠.
基于先行策略的可达性分析算法伪代码①如下.
1//基于先行策略的可达性分析算法伪代码2while code!=null do3 //模式匹配addJavascriptInterface4 suspect←find(“addJavascriptInterface”)5 setS.add(suspect)//集合S保存可疑点6 code←nextFile()//读取下一反编译文件7end while8//对所有可能入口点建立对应ICFG9setG←buildICFGs()//集合G保存ICFG10//分析ICFG11for each g∈setGdo12 for each x∈setSdo13 if g.getNodeSet().contains(x) then14 //ICFG点集中有可疑点,必存在可达路径15 path←getPath(g, g.Entry, x)16 //保存可达路径,以便动态验证17 mapP.add(x, path)//集合P为map类型18 else then19 //可疑点不在点集,必无可达路径,空操作20 end for each21end for each
1.2.1WebView组件远程代码执行漏洞检测方法
由于WebView组件远程代码执行漏洞的产生需要具备两个条件:使用addJavascriptInterface函数、网络流量可篡改或可远程传入html文件.
在应用全路径的过程间控制流图(inter-procedural control flow graph, ICFG)中进行可达性分析时,需要消耗大量的计算,而且Android应用多个入口点的特性使得需要建立多张ICFG,若对全部ICFG进行路径搜索,则开销过于巨大. 为了降低计算开销,利用ICFG的单一入口、单一出口的特性,先搜索ICFG点集,仅对存在可疑点的ICFG进行路径搜索. 这种基于先行策略的方式可以大幅减少需要路径搜索的ICFG数量,有效降低计算开销. 该基于先行判断的可达性分析具体流程如下:
步骤1 对所有使用了addJavascriptInterface函数的代码定位,标记为漏洞可疑点si,存入集合S={si}.
步骤2 对所有可能入口点建立过程间控制流图. ICFG的集合为G={gk(V,E)},其中点集V={vm},边集E={en},可能入口点为MANIFEST文件声明的Activity、Service等.
由上可知,仅对集合P进行动态验证,即可排除不可达的可疑点. 该基于先行策略的可达性分析算法伪代码如代码①所示.
在使用addJavascriptInterface函数时需要提供两个参数,第一个参数是接口Java类对象,即含有声明了@JavascriptInterface注释的函数的Java类的对象,第二个参数是接口名字. 这里接口名字相当于是第一个参数的别名,html页面中以该接口名字识别对应的Java对象,从而调用接口方法. 为了动态验证时真实模拟攻击过程,还需得到这两个参数的具体值. 由于存在参数外部传入的情况,仅在敏感函数所在代码段,无法确保获得这两个参数值.
数据依赖分析可解决该问题. 建立过程间数据流图(inter-procedural data flow graph, IDFG),进而得到数据依赖图(data dependence graph, DDG). DDG上可以得到数据依赖的接口Java类对象与接口名. 根据接口Java类对象,继续找到相应该类中声明了@JavascriptInterface注释的函数. 针对API16及以下编译的Android应用,找到接口类内所有public修饰的函数为接口函数. 最终,将找到的接口函数与接口名字交由动态验证部分继续处理.
动态验证时,通过模拟输入获取到应用页面与执行路径的对应信息,然后根据可达性分析保存的路径信息,生成对应的自动化验证脚本. 执行自动化脚本,在可疑点对应的WebView开启后,在html页面的body段中加上“onload=接口名字.接口函数”字段. 同时,通过对接口函数进行hook,将原有功能替换成向特定Service进程发送Intent消息功能,消息内容为自身函数名. 事先开启一个Service进程接收这些Intent消息,若接收成功,则漏洞存在.
1.2.2WebView File域同源策略绕过漏洞检测方法
对WebView File域同源策略绕过漏洞的检测与对远程代码执行漏洞的检测基本流程相似,这里进行简要说明.
WebView File域同源策略绕过漏洞的产生需要4个条件:包含WebView的组件可以导出、WebView允许使用Javascript代码、WebView允许使用File协议、File文件的URL可被攻击者控制. 因此,该漏洞不像远程代码执行漏洞一样有明确的漏洞敏感函数. 故检测方法主要有如下几点不同:
① 漏洞可疑点设定在每个可以导出的WebView对象被实例化的地方.
② 可达性分析后,再次根据ICFG,判断对于每个可达的WebView对象是否相应地对Javascript代码与File协议的使用进行了限制. 通常通过WebView中的getSettings内的setAllowFileAccess函数、setJavaScriptEnabled函数进行限制,这些函数目前默认状态值均为flase.
③ 若根据ICFG得到有对WebView进行限制,则获取限制状态值. 此处特殊的是,状态值的赋值往往采用直接传入方式,如setAllowFileAccess(true)形式,通常不会通过远程传入或再次封装等操作,所以在此处多增加一个判断,直接根据ICFG获取这些限制的代码位置,从反编译文件中直接查看这些状态值是否采用直接传入的方式. 对于直接传入的状态值,便无需再进行数据依赖分析,省去了建立IDFG、DDG的复杂过程.
④ 只有当Javascript代码、File协议的限制都被允许,即设置为true的情况下,才进行动态验证.
⑤ 动态验证时仍依靠修改网络流量方式触发,使应用读取预存在应用私有文件夹下特定文件的内容,若读取成功,则漏洞存在.
为确保检测结果准确,XWebViewDigger先对Android应用的APK文件进行深度静态分析,然后动态运行应用对静态分析结果进行验证. XWebViewDigger的整体架构图如图2所示.
图2中加粗的框体是XWebViewDigger的核心模块. 其中,静态分析部分以可达性分析模块与数据依赖分析模块为主要组成模块,动态验证部分主要依赖对系统状态、应用状态的监控确认漏洞真实性.
XWebViewDigger静态分析过程依托Amandroid为引擎,可以比较稳定地对应用建立ICFG、IDFG、DDG. 对于待检Android应用,XWebViewDigger首先利用模式匹配模块,获得WebView组件漏洞的可疑点在代码中的位置信息. 然后利用可达性分析模块,对所有可能入口建立相应的ICFG,利用图路径搜索算法,得到从入口点到可疑点所有可能路径. 最后,对于可达的可疑点,构建IDFG与DDG,进行数据流追踪,获得数据依赖信息,以便动态验证使用.
2.2.1模式匹配模块
模式匹配模块负责发现可能产生漏洞的可疑点,根据漏洞特征进行模式匹配,标注可疑点代码位置、上下文参数等信息.
2.2.2可达性分析模块
由于Android应用的模块化特点,其本身没有固定程序入口点,因此,XWebViewDigger先根据APK文件中MANIFEST文件的声明信息,将声明的Activity、Service等作为可能入口点. 对于每一个可能入口点生成虚拟主函数,建立ICFG. 如果从每一个入口点都无法到达可疑点,则无法调用可疑点处的代码,因此不存在漏洞,排除该可疑点. 对于可达的可疑点,保存所有可达路径信息. 进行可达性分析是为了降低一定的误报率,并提高后续工作效率,减少数据依赖分析与动态验证的成本.
2.2.3数据依赖分析模块
对于可达的可疑点,建立对应ICFG的IDFG、DDG,分析可疑点附近传入、传出的数据,进行数据流追踪,最终将数据依赖信息与可达路径信息一起,交于动态验证部分.
动态验证部分是确保检测结果无误报的核心部分,模拟真实攻击行为,通过对系统状态与应用状态的监控,确认攻击是否成功,进而确认可疑点是否可以真实触发,漏洞是否真实存在. 该部分主要包括模拟输入模块、网络数据控制模块、监控模块组成.
2.3.1模拟输入模块
模拟输入模块主要保证Android应用以指定路径信息执行. 该模块通过分析布局文件获取界面需要点击、输入的位置,遍历点击位置,同时依靠对系统监控,获取点击位置对应的系统交互信息,如进程间通信、启动的Activity、调用的API,最终参照静态分析得到的路径信息,生成对应的运行脚本. 若需输入用户名、密码等,通过预置脚本填充.
2.3.2网络数据控制模块
由于WebView组件漏洞需要通过篡改网络数据流量触发,因此网络数据控制模块本质上相当于一个Android系统上的抓包器,默认通过127.0.0.1:8888进行代理转发. 当运行到可疑点时,该模块会自动修改网络流量,触发漏洞.
2.3.3监控模块
监控模块通过对系统、应用的状态监测与控制,自动验证漏洞触发是否成功. 监控模块通过修改rom方式实现对系统状态的获取,通过对应用的关键部分进行hook以发送漏洞触发情况,开启一个Service接收这些信息. 一旦接收到漏洞触发成功的消息,即可确认漏洞真实存在.
以Core i7 3.6 GHz、32 G内存、Ubuntu16.04设备为测试环境,对XWebViewDigger进行三轮实验.
第一轮,先以特定编写的存在漏洞的基准测试集进行实验,成功发现相关漏洞及其定位情况.
第二轮,在应用市场首页推荐的100个应用中随机下载30个,利用XWebViewDigger成功发现6个应用存在WebView组件远程代码执行漏洞,并且经人工确认后,漏洞真实存在,没有产生误报. 利用商业检测平台[10]检测这30个应用,共发现11个应用存在WebView组件远程代码执行漏洞,经人工确认,其中7个应用真实存在,4个应用为误报. 具体分析漏报的1个应用,漏报原因为反编译失败.
第三轮,将应用市场的应用分为8类,每类对推荐的前20个应用随机下载,总共50个应用. 其中单独增加会议类应用,该类应用是在重大会议等活动期间发布的极有针对性特征的一类应用. 该类应用往往因开发时间紧迫,应用有价值时间有限等因素而忽视安全问题. 成功发现共12个应用存在WebView组件远程代码执行漏洞,如表1所示.
表1 实验检测结果统计表Tab.1 Test result table of classified applications
本文通过分析WebView组件漏洞原理、触发机制等,设计了一种静态分析指导动态验证的自动化漏洞检测与验证方法ADV,并实现相应原型工具XWebViewDigger. 通过实验,可以成功检测出WebView组件漏洞,并通过可达性分析与动态验证解决传统静态匹配误报率高的问题,通过数据依赖分析提高自动化程度. 由于ADV在方法上具有普适性,下一步将继续扩展检测支持的漏洞类型,不但可以检测WebView漏洞,还可检测其他类型漏洞,从而提高整个Android应用漏洞检测工具的自动化程度,有效降低人工分析和验证成本.