1、ZIP文件目录遍历简介

因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件。如果被覆盖掉的文件是动态链接so、dex或者odex文件,轻则产生本地拒绝服务漏洞,影响应用的可用性,重则可能造成任意代码执行漏洞,危害用户的设备安全和信息安全。比如近段时间发现的“寄生兽”漏洞、海豚浏览器远程命令执行漏洞、三星默认输入法远程代码执行漏洞等都与ZIP文件目录遍历有关。

阿里聚安全的应用漏洞扫描服务,可以检测出应用的ZIP文件目录遍历风险。另外我们发现日本计算机应急响应小组(JPCERT)给出的修复方案存在缺陷。如果使用不当(它提供的示例文档就使用错误),可能起不到防止ZIP文件目录遍历的作用,并且国内有修复方案参考了此方案。

2、漏洞原理和风险示例

2.1 漏洞原理

在Linux/Unix系统中“../”代表的是向上级目录跳转,有些程序在当前工作目录中处理到诸如用“../../../../../../../../../../../etc/hosts”表示的文件,会跳转出当前工作目录,跳转到到其他目录中。

Java代码在解压ZIP文件时,会使用到ZipEntry类的getName()方法,如果ZIP文件中包含“../”的字符串,该方法返回值里面原样返回,如果没有过滤掉getName()返回值中的“../”字符串,继续解压缩操作,就会在其他目录中创建解压的文件。

如我们构造的ZIP文件中有如下文件:

进行解压的代码如下,没有对getName进行过滤:

解压操作时的日志:

此ZIP文件存放在SD卡中,想让解压出来的所有文件也存在SD卡中,但是a_poc.txt文件却存在了应用的数据目录中:

2.2 风险示例

以海豚浏览器远程代码执行漏洞为例。

海豚浏览器的主题设置中允许用户通过网络下载新的主题进行更换,主题文件其实是一个ZIP压缩文件。通过中间人攻击的方法可以替换掉这个ZIP文件。替换后的ZIP文件中有重新编译过的libdolphin.so。此so文件重写了JNI_OnLoad()函数:

此so文件以“../../../../../../../../../../data/data/mobi.mgeek.TunnyBrowser/files/libdolphin.so”的形式存在恶意ZIP文件中。海豚浏览器解压恶意ZIP文件后,重新的libdolphin.so就会覆盖掉原有的so文件,重新运行海豚浏览器会弹出Toast提示框:

能弹出Toast说明也就可以执行其他代码。

这里分析下此漏洞产生的原因是:

1、主题文件其实是一个ZIP压缩包,从服务器下载后进行解压,但是解压时没有过滤getName()返回的字符串中是否有“../”:

2、动态链接库文件libdolphin.so,并没有放在应用数据的lib目录下,而是放在了files目录中:

加载使用的地方是com.dolphin.browser.search.redirect包中的SearchRedirector:

应用使用的是System.load()来加载libdolphin.so而非System.loadLibrary(),在Android中,System.loadLibrary()是从应用的lib目录中加载.so文件,而System.load()是用某个.so文件的绝对路径加载,这个.so文件可以不在应用的lib目录中,可以在SD卡中,或者在应用的files目录中,只要应用有读的权限目录中即可。

在files目录中,应用具有写入权限,通过网络中间人攻击,同时利用ZIP文件目录遍历漏洞,替换掉文件libdolphin.so,达到远程命令执行的目的。

应用的lib目录是软链接到了/data/app-lib/应用目录,如果libdolphin.so文件在lib目录下就不会被覆盖了,第三方应用在执行时没有写入/data/app-lib目录的权限:

3、JPCERT修复方案的研究

在研究中我们发现JPCERT提供的修复方案存在缺陷。它是利用Java的File类提供的getCanonicalPath()方法过滤掉zipEntry.getName()返回的字符串中所包含的“../”,然后检查这个字符串是否是以要解压到的目标目录字符串为开头,如果是,返回getCanonicalPath()获取到的字符串,如果不是,则抛出异常:

但是在JPCERT给出的示例代码中,对validateFilename()的调用对于APP来说不会达到防止任意目录遍历的目的:

其使用“.”,作为要解压到的目的目录,“.”表示当前目录,经测试APP进程的当前工作目录是根目录“/”:

查看进程状态,得到的APP进程的当前工作目录cwd是链接到了根目录:

如下的Demo,如果采用JPCERT示例中validateFilename(entry.genName(), “.”)的调用方式,还是会产生目录遍历读到系统配置文件:

读到的hosts文件内容:

正确的调用validateFilename()形式是传入的要解压到的目的目录不要用“.”,而是指定一个绝对路径。

4、阿里聚安全对开发者建议

  1. 对重要的ZIP压缩包文件进行数字签名校验,校验通过才进行解压。

  2. 检查Zip压缩包中使用ZipEntry.getName()获取的文件名中是否包含”../”或者”..”,检查”../”的时候不必进行URI Decode(以防通过URI编码”..%2F”来进行绕过),测试发现ZipEntry.getName()对于Zip包中有“..%2F”的文件路径不会进行处理。

  3. 在应用上线前使用阿里聚安全的安全扫描服务,尽早发现应用的安全风险。

阿里聚安全扫描器建议修复方案:在使用java.util.zip包中ZipInputStream类的进行解压操作时,进行检查。示例如下

也可以使用java.util.zip包中的ZipFile类,直接读取Zip包中的所有entries,然后检查getName()的返回值是否包含“../”:

5、参考

[1] https://www.jpcert.or.jp/present/2014/20140910android-sc.pdf
2] [《海豚浏览器与水星浏览器远程代码执行漏洞详解》
3] [《影响数千万APP的安卓APP“寄生兽”漏洞技术分析》
4] [《三星默认输入法远程代码执行》
[5] http://www.oracle.com/technetwork/articles/java/compress-1565076.html
[6] http://stackoverflow.com/questions/1099300/whats-the-difference-between-getpath-getabsolutepath-and-getcanonicalpath
[7] http://stackoverflow.com/questions/7016391/difference-between-system-load-and-system-loadlibrary-in-java

Android 安全开发之 ZIP 文件目录遍历的更多相关文章

  1. Android安全开发之ZIP文件目录遍历

    1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件.如果被覆盖掉的文件是动态链接s ...

  2. Android混合开发之WebViewJavascriptBridge实现JS与java安全交互

    前言: 为了加快开发效率,目前公司一些功能使用H5开发,这里难免会用到Js与Java函数互相调用的问题,这个Android是提供了原生支持的,不过存在安全隐患,今天我们来学习一种安全方式来满足Js与j ...

  3. Android混合开发之WebView与Javascript交互

    前言: 最近公司的App为了加快开发效率选择了一部分功能采用H5开发,从目前市面的大部分App来讲,大致分成Native App.Web App.Hybrid App三种方式,个人觉得目前以Hybri ...

  4. Android混合开发之WebView使用总结

    前言: 今天修改项目中一个有关WebView使用的bug,激起了我总结WebView的动机,今天抽空做个总结. 混合开发相关博客: Android混合开发之WebView使用总结 Android混合开 ...

  5. Android驱动开发之Hello实例

    Android驱动开发之Hello实例:   驱动部分 modified:   kernel/arch/arm/configs/msm8909-1gb_w100_hd720p-perf_defconf ...

  6. Android安全开发之WebView中的地雷

    Android安全开发之WebView中的地雷 0X01 About WebView 在Android开发中,经常会使用WebView来实现WEB页面的展示,在Activiry中启动自己的浏览器,或者 ...

  7. android软件开发之webView.addJavascriptInterface循环渐进【二】

    本篇文章由:http://www.sollyu.com/android-software-development-webview-addjavascriptinterface-cycle-of-gra ...

  8. android软件开发之webView.addJavascriptInterface循环渐进【一】

    本篇文章由:http://www.sollyu.com/android-software-development-webview-addjavascriptinterface-cycle-of-gra ...

  9. Android NDK开发之C调用Java及原生代码断点调试(二)

    上一篇中,我们主要学习了Java调用本地方法,并列举了两大特殊实例来例证我们的论据,还没学习的伙伴必须先去阅读下,本次的学习是直接在上一篇的基础上进行了.点击:Android NDK开发之从Java与 ...

随机推荐

  1. Java中随机数生成的问题

    [生成随机数序列] 我们只能利用Math.random()方法只能生成一个在[0,1)之间的double类型浮点数. 但如果我们想要生成[min, max]之间的随机整数时该怎么办呢? 此时可以用: ...

  2. HDU 4687 Boke and Tsukkomi (一般图最大匹配)【带花树】

    <题目链接> 题目大意: 给你n个点和m条边,每条边代表两点具有匹配关系,问你有多少对匹配是冗余的. 解题分析: 所谓不冗余,自然就是这对匹配关系处于最大匹配中,即该匹配关系有意义.那怎样 ...

  3. 关于cin的缓存区影响效果

    1. 当缓冲区中有残留数据时,cin函数会直接去读取这些残留数据而不会请求键盘输入.而且,回车符也会被存入输入缓冲区中. int num{}; while(cin>>num) cout&l ...

  4. switch反汇编

    以下总结为debug模式

  5. suctf逆向部分

    自己真的菜,然后在网上找了一篇分析pyc反编译后的文件然后进行手撸opcode,过程真痛苦 http://www.wooy0ung.me/writeup/2017/10/11/0ctf-quals-2 ...

  6. String,StringBuffer与StringBuilder的区别|线程安全与线程不安全

    https://www.cnblogs.com/xingzc/p/6277581.html

  7. SpringBoot使用WebJars

    本人主要做的是java,但是从第一份工作开始,就一直在做一个写前端又写后端的程序员,相信很多朋友和我一样,不仅要会后台代码,还要懂得很多的前端代码,例如javascipt和css样式. 本文就为大家简 ...

  8. 使用C#的is、as操作符来转型

    is检查对象是否兼容于指定类型,返回Boolean值true或false.使用is永远不会抛出异常. 例:Object o=new Object(); bool b1=(o is Object);// ...

  9. ARC101E - Ribbons on Tree

    题目链接 ARC101E - Ribbons on Tree 题解 令边集\(S \subseteq E\) 设\(f(S)\)为边集S中没有边被染色的方案数 容斥一下,那么\(ans = \sum_ ...

  10. sql去除重复列(行)

    1.存在两条完全相同的纪录   这是最简单的一种情况,用关键字distinct就可以去掉   例子: select distinct * from table(表名) where (条件)   2.存 ...