Android zip 文件目录遍历漏洞
概述
zip
类型的压缩包文件中允许存在 ../
类型的字符串,用于表示上一层级的目录。攻击者可以利用这一特性,通过精心构造 zip
文件,利用多个 ../
从而改变 zip
包中某个文件的存放位置,达到替换掉原有文件的目的。
那么,如果被替换掉的文件是是 .so
、.dex
或 .odex
类型文件,那么攻击者就可以轻易更改原有的代码逻辑,轻则产生本地拒绝服务漏洞,影响应用的可用性,重则可能造成任意代码执行漏洞,危害应用用户的设备安全和信息安全。比如寄生兽漏洞、海豚浏览器远程命令执行漏洞和三星默认输入法远程代码执行等著名的安全事件。
基本原理
在 Linux/Unix
系统中 ../
代表的是上一层级的目录,有些程序在当前工作目录中处理到诸如 ../../../../../../../../../../../etc/hosts
表示的文件,会跳转出当前工作目录,跳转到到其他目录中对应的 hosts
目录。
Java
代码在解压 zip
文件时,会使用到 ZipEntry
类的 getName()
方法,如果 zip
文件中包含 ../
的字符串,该方法返回值会原样返回。如果没有过滤掉 getName()
返回值中的 ../
字符串,继续解压缩操作,就会在其他目录中创建解压的文件。
风险示例
海豚浏览器海豚浏览器的主题设置中允许用户通过网络下载新的主题进行更换,主题文件其实是一个 zip
压缩文件,里面有如下文件:
1 | unzip -l Red_roof.dwp.orig |
dwp
文件是海豚浏览器自己定义的主题文件包,本质上是一个zip
包。
通过中间人攻击的方法,替换掉这个 zip
文件。用来替换原有的 zip
文件的恶意 zip
文件中,有重新编译的 libdolphin.so
。由于海豚浏览器的 libdolphin.so
文件在系统中的存放路径为 ../../../../../../data/data/mobi.mgeek.TunnyBrowser/files/libdolphin.so
,那么,我们只需要将我们重新编译的 libdolphin.so
文件以 ../../../../../../data/data/mobi.mgeek.TunnyBrowser/files/libdolphin.so
的方式命名,并放置在我们的恶意 zip
包中:
1 | unzip -l Red_roof.dwp |
那么,当海豚浏览器下载到攻击者精心设计的 zip
包并完成解压之后,那么 libdolphin.so
就会被替换。
如此一来,攻击者就可以轻易地把有风险的代码植入到应用中去,从而实现某些目的。
可以使用如下 Python
代码生成一个可以触发该漏洞的 zip
包:
1 | import zipfile |
修复方案
- 对重要的
zip
压缩包文件进行数字签名校验,校验通过才进行解压 - 检查
zip
压缩包中使用ZipEntry.getName()
获取的文件名中是否包含../
或者..
字符 - 更换
zip
解压方式,不使用ZipEntry.getName()
的方式,使用ZipInputStream
替代
Google
建议的修复方案:
1 | InputStream is = new InputStream(untrustedFileName); |