返回介绍

25.1 解压文件漏洞分析

发布于 2024-10-10 22:32:23 字数 4239 浏览 0 评论 0 收藏 0

25.1.1 漏洞场景

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

代码看上去很简单,但是这段代码中存在一个问题,就是 zipEntry.getName 方法,这个方法返回的是 zip 文件中的子文件名称,按照正常逻辑,解压这个子文件到本地都是直接用相同的名字即可,但是这里解压 zip 文件存在一个漏洞:zip 文件中的子文件名格式没有格式要求,也就是可以包含特殊字符。但是在 PC 系统中文件名是有限制的,比如 Windows 中,如图 25-1 所示。在 Linux 中,如图 25-2 所示。

图 25-1 Windows 中文件命名限制

图 25-2 Linux 中文件命名限制

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

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

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

这里的 ZipEntry 可以指定随意的名称,而这个名称就是文件在 zip 文件中的文件名。那么如果 zip 包被人恶意的拦截,然后进行修改,这里可以使用 ZipInputStream/ZipOutputStream 类,写一个简单的小程序,就可以把恶意文件写入到 zip 中。

25.1.2 漏洞原因分析

因为文件名没有限制,所以攻击者可以把恶意文件名称命名为:../../../../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 本身的权限来写入沙盒数据。

25.1.3 漏洞案例分析

上面分析完了漏洞,下面就用一个简单的例子来看看问题吧,从上面的分析知道,在本地系统中命名这样特殊格式的文件,在进行压缩成 zip 文件是不行的,因为系统不支持这种命名格式,所以这里需要写一个小程序,把这个特殊的文件名的文件压缩成 zip,便于测试,然后再进行解压,如下所示:

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

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

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

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

25.1.4 漏洞修复

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

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

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

现在 Android 中动态加载技术和插件化开发已经很普遍了,但是在下载这个阶段一定要做好防护工作。如果你的项目现在正好有解压 zip 的功能,请尽快去审查一下项目中解压有没有做防护,没有的话就尽快加上吧!

25.1.5 漏洞总结

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

·ZipEntry 对压缩文件名没有特殊要求。

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

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

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文