Android中的漏洞真的很多,一不小心就踩到坑了,最近开发过程中遇到一个问题,解决发现一个很大的漏洞,而这个漏洞到现在也没有修复,google也没有想过修复,下面就来看看这个漏洞的场景。
Android中现在开发过程中会有很多场景中使用到解压缩文件,比如动态加载机制,可能下载了apk/zip文件,然后在本地做解压工作,还有就是一些资源在本地占用apk包的大小,就也打包成zip放到服务端,使用的时候在下发。本地在做解压工作。那么在Android中解压zip文件,使用的是ZipInputStream和ZipEntry类,代码比较简单:
代码看上去很简单,但是这段代码中就存在一个问题,就是那个zipEntry.getName方法,这个方法返回的是zip文件中的子文件名称,按照正常逻辑,解压这个子文件到本地都是直接用相同的名字即可,但是这里zip文件就存在一个漏洞:
zip文件中的子文件名格式没有格式要求,也就是可以包含特殊字符。
但是在系统中是有限制的,比如Windows中:
在Linux中:
这些系统中是不允许文件名包含一些特殊字符的,但是在ZipInputStream/ZipOutputStream类却是可以的。
也就是说使用ZipOutputStream类进行压缩文件,这里可以对文件名不做任何限制,压缩代码也简单:
只用ZipEntry类做单个文件压缩:
这里的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,便于测试,然后在进行解压:
先进行压缩文件,方便测试,产生一个demo.zip文件,然后在进行解压验证漏洞问题,这里验证问题的重点是:
这里把zip中需要解压的文件名前加上前缀:../../../data/data/cn.wjdiankong.androidzipleakdemo/ 这样解压之后的目录就是本应用的沙盒中了,注意这里的../这样的符号不要太多,只要能回到根目录就可以了。
这里为了方便,直接使用echo命令,写入aaa内容到demo.txt文件中,然后点击压缩,再次查看多了demo.zip文件了:
看到了,这里就把zip中的恶意文件demo.txt释放到了应用的沙盒中了,如果这个文件是dex或者啥,替换原来应用的一些重要文件,那么后果会很严重的。
上面的问题,我们了解了,主要是因为ZipEntry在进行压缩文件的时候,名称没有做任何限制,而在Android系统中../这种特殊符号代表的是回到上层目录,又因为这个解压工作在本应用中,可以借助app的自生权限,把恶意文件名改成:../../../data/data/...即可在解压的时候把文件解压到了应用的沙盒中。
那么其实问题在于最后一步解压,因为我们不会去修改解压之后的文件名,默认都是直接解压即可,那么这里修复这个漏洞问题很简单了,有很多种方式,核心就一个就是不要让有特殊字符,比如:../ 的文件成功解压,或者是解压到本地文件名称不能包含这种特殊字符即可:
这里可以直接过滤来防护这个问题了。
上面分析了现在应用很多都有从服务端下载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解压的速度检查项目,如果有的话,看看有没有添加防护过滤,保证我们的项目没有这个漏洞的风险!
更多内容:点击这里
关注微信公众号,最新技术干货实时推送