Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中

http://blog.csdn.net/jiangwei0910410003/article/details/52118575

目录(?)[-]

  1. 一前言
  2. 二漏洞场景分析
  3. 三漏洞出现的原因
  4. 四漏洞案例分析
  5. 六问题延展
  6. 七漏洞总结
  7. 八总结

一、前言

Android中的漏洞真的很多,一不小心就踩到坑了,最近开发过程中遇到一个问题,解决发现一个很大的漏洞,而这个漏洞到现在也没有修复,google也没有想过修复,下面就来看看这个漏洞的场景。


二、漏洞场景分析

Android中现在开发过程中会有很多场景中使用到解压缩文件,比如动态加载机制,可能下载了apk/zip文件,然后在本地做解压工作,还有就是一些资源在本地占用apk包的大小,就也打包成zip放到服务端,使用的时候在下发。本地在做解压工作。那么在Android中解压zip文件,使用的是ZipInputStream和ZipEntry类,代码比较简单:

Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中_第1张图片

代码看上去很简单,但是这段代码中就存在一个问题,就是那个zipEntry.getName方法,这个方法返回的是zip文件中的子文件名称,按照正常逻辑,解压这个子文件到本地都是直接用相同的名字即可,但是这里zip文件就存在一个漏洞:

zip文件中的子文件名格式没有格式要求,也就是可以包含特殊字符。

但是在系统中是有限制的,比如Windows中:

Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中_第2张图片

在Linux中:

Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中_第3张图片

这些系统中是不允许文件名包含一些特殊字符的,但是在ZipInputStream/ZipOutputStream类却是可以的。


也就是说使用ZipOutputStream类进行压缩文件,这里可以对文件名不做任何限制,压缩代码也简单:

Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中_第4张图片

只用ZipEntry类做单个文件压缩:

Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中_第5张图片

这里的ZipEntry可以指定随意的名称,而这个名称就是文件在zip中的文件名。但是问题是这里对名称没有任何限制,那么如果我们的zip包被人恶意的拦截,然后进行修改,当然这里他可以使用ZipInputStream/ZipOutputStream类,写一个简单的小程序,就可以把恶意文件写入到zip中


三、漏洞出现的原因

这里的恶意漏洞的问题就在于:

因为文件名没有限制,所以攻击者可以把恶意文件名称命名为:../../../../data/data/xxx.xxx.x/hacker.dex,因为Android是基于Linux系统的,在Linux系统中../这个符号代表是回到上层目录,那么这里可以多弄几个这个符号,这样就会回到Android系统的根目录,然后在进入当前应用的沙盒目录下,写一个文件了。当然这里只能写入本应用中,而不能写入其他应用。


存在的风险:比如现在知道了一个应用的沙盒数据的详细信息,比如一些隐私数据存放在SharedPreferences.xml中,或者是有动态加载机制,需要加载的dex存放在一个目录中,那么这时候我们可以利用这个漏洞,把几个恶意文件,命名成

../../../../data/data/xxx.xxx.xxx/shared_pref/info.xml,或者是../../../../data/data/xxx.xxx.xxx/dexfile/dynamic.dex等

这样在使用ZipEntry进行解压文件的时候,因为直接使用了ZipEntry.getName方法或者文件名,然后直接释放解压到本地了,所以这时候就相当于替换了本应用的沙盒数据了,这个也是利用了app本身的权限来写入沙盒数据。


四、漏洞案例分析

上面分析完了漏洞,下面就用一个简单的例子来看看问题吧:

因为,我们上面分析知道,在本地系统中命名这样特殊格式的文件,在进行压缩成zip文件是不行的,因为系统不支持这种命名格式,所以这里需要写一个小程序,把这个特殊的文件名的文件压缩成zip,便于测试,然后在进行解压:

Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中_第6张图片

先进行压缩文件,方便测试,产生一个demo.zip文件,然后在进行解压验证漏洞问题,这里验证问题的重点是:

Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中_第7张图片

这里把zip中需要解压的文件名前加上前缀:../../../data/data/cn.wjdiankong.androidzipleakdemo/ 这样解压之后的目录就是本应用的沙盒中了,注意这里的../这样的符号不要太多,只要能回到根目录就可以了。

Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中_第8张图片

这里为了方便,直接使用echo命令,写入aaa内容到demo.txt文件中,然后点击压缩,再次查看多了demo.zip文件了:

Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中_第9张图片

看到了,这里就把zip中的恶意文件demo.txt释放到了应用的沙盒中了,如果这个文件是dex或者啥,替换原来应用的一些重要文件,那么后果会很严重的。


五、如何避免这个漏洞问题

上面的问题,我们了解了,主要是因为ZipEntry在进行压缩文件的时候,名称没有做任何限制,而在Android系统中../这种特殊符号代表的是回到上层目录,又因为这个解压工作在本应用中,可以借助app的自生权限,把恶意文件名改成:../../../data/data/...即可在解压的时候把文件解压到了应用的沙盒中。

那么其实问题在于最后一步解压,因为我们不会去修改解压之后的文件名,默认都是直接解压即可,那么这里修复这个漏洞问题很简单了,有很多种方式,核心就一个就是不要让有特殊字符,比如:../ 的文件成功解压,或者是解压到本地文件名称不能包含这种特殊字符即可:

Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中_第10张图片

这里可以直接过滤来防护这个问题了。


六、问题延展

上面分析了现在应用很多都有从服务端下载zip文件,然后在本地进行解压的功能,在解压的过程中默认不回去进行文件名的操作,所以就存在一些特殊字符的文件名被释放到了本地,从而产生重大后果。但是这里有一个前提,就是你需要下载的zip文件被攻击者拦截到了,并且替换了。但是如果在下载的过程中就做一层安全其实也是可以的,比如使用https协议,然后在结合文件的MD5比对功能,这样就可以防止zip包被人拦截替换了。本地也就不会存在这样的风险了。

所以现在Android中动态加载技术和插件化开发已经很普遍了,但是在下载这个阶段一定要好防护工作,一个是服务端可以采用https协议,而客户端需要做文件的MD5比对,以及这种解压工作的防护过滤。

如果你的项目现在正好有解压zip的功能,请看完这篇文章之后,尽快去审查一下项目中解压有没有做防护,没有的话就尽快加上吧!


七、漏洞总结

本文主要介绍了一个不起眼的漏洞,但是隐藏着很严重的问题,这个漏洞主要是因为如下几点综合产生的:

1、ZipEntry对压缩文件名没有特殊要求

2、在Android系统中../特殊字符代表着回到上级目录

3、借助本应用的权限,把数据写入沙盒中

因为这三点,就可以在解压过程中把恶意文件解压到应用的沙盒中,当然这里有一个前提就是你的zip包被人拦截并且篡改加入这种特殊字符的恶意文件了。


关于这个漏洞的修复,Google一直没有修复,只是在Api中做了提醒:


可以看到google对该方法给出了一个安全提示,提示开发者如果该方法的返回值中包含有"../"跳转符,需要特别注意不要将文件写到了目标文件夹之外。如果不对"../"跳转符做过滤,就有可能遍历目录,在解压zip文件时以本app的权限覆盖任意文件。


项目下载:http://download.csdn.net/detail/jiangwei0910410003/9594958


八、总结

人生处处是坑,Android系统处处是漏洞,开发中碰到这个问题,真的很难注意到,但是却隐藏这很大的风险,所以有项目中用到了zip解压的速度检查项目,如果有的话,看看有没有添加防护过滤,保证我们的项目没有这个漏洞的风险!



你可能感兴趣的:(技术聚集)