近日,专注于开源及云安全监控防范工作的 Snyk 公司披露了一种可能会造成任意文件被覆写的安全漏洞,称为 Zip Slip。其相应的攻击手段是创建一种特制的ZIP压缩文件,在其中引用会对目录进行遍历的文件名。受该风险影响的项目多达数千个,包括 AWS Toolkit for Eclipse、Spring Integration、LinkedIn的Pinot OLAP数据库、 Apache/TwitterHeron、Alibaba JStorm、Jenkins 和 Gradle 等等。各大云服务提供商也纷纷发现了该问题的存在,InfoQ将对此问题的进展持续追踪。

据该公司所分析,这一安全漏洞对于 Java 生态系统来说影响尤其严重,这是因为在 Java 生态中缺少对压缩文件进行高层次处理功能的这样一种集中式的库。目前已知包含这一漏洞的Java类库包括Java java.util.zip、Apache commons-compres、 Apache Ant、ZeroTurnaround 的 zt-zip 和 zip4j。Snyk 的 CEO Guy Podjarny 同时也向InfoQ表示,由于该漏洞所影响的压缩文件格式是那些解压缩类库支持的、并且允许在压缩文件中出现相对路径的文件格式,因此 JAR/EAR/WAR 都有可能成为潜在的受害者。

文件遍历攻击的目标是访问保存在 root 目录之外的文件或文件夹,只需在引用文件地址的变量中添加 “点-点-斜杠(…/)“或类似的符号,又或者是使用绝对文件路径,攻击者就有可能访问保存在文件系统中的任意文件或目录,例如应用程序的源代码或是配置文件,乃至重要的系统文件。举例来说,如果某个ZIP压缩文件中包含一个路径为"…/…/file.exe"的文件,那么在进行解压时,该文件的实际地址就会脱离目标文件夹之外(注:常见的压缩工具并不支持这种路径,但ZIP格式本身并没有这种限制)。这种情形可能会出现在服务端,也可能出现在客户端。所导致的结果可能是恶意文件被写入磁盘,或是敏感的文件被覆写。如果某个可执行文件或配置文件被某个包含了恶意代码的文件所覆盖,那么就有可能导致恶意代码被执行的问题。

Snyk 的白皮书通过以下这段代码举例说明在 Java 程序中出现的代码漏洞片段:

__Thu Jun 07 2018 19:13:37 GMT+0800 (CST)____Thu Jun 07 2018 19:13:37 GMT+0800 (CST)__Enumeration entries=zip.getEntries();while(entries.hasMoreElements()){ZipEntry e =entries.nextElement();File f = new File(dir, e.getName());InputStream input =zip.getInputStream(e);IOUtils.copy(input, write(f));} 
__Thu Jun 07 2018 19:13:37 GMT+0800 (CST)____Thu Jun 07 2018 19:13:37 GMT+0800 (CST)__

在这段代码中,e.getName() 在与目标目录 dir 进行字符串拼接之前没有经过任何校验,就确定了Java File对象f的最终地址。如果在文件名中包含了向上遍历的目录路径(比如路径以 …/…/ 开头),那么在执行 IOUtils.copy 方法时,该文件就会被写入目标目录之外的地址。

一旦你意识到这种写法可能会被恶意利用,那么对该漏洞的防范倒是非常直接了当的。因为ZIP压缩文件没有理由需要将一个文件写入解压目录之外,所以你只需简单地进行检查就可以防止它发生:

__Thu Jun 07 2018 19:13:37 GMT+0800 (CST)____Thu Jun 07 2018 19:13:37 GMT+0800 (CST)__String canonicalDirPath=dir.getCanonicalPath();String canonicalDestPath=e.getName().getCanonicalPath();if(!canonicalDestPath.startsWith(canonicalDirPath)){throw new ArchiverException("Entry is outside of the target dir: " + e.getName());}
__Thu Jun 07 2018 19:13:37 GMT+0800 (CST)____Thu Jun 07 2018 19:13:37 GMT+0800 (CST)__

Snyk 的开发总监 Simon Maple 向 InfoQ 表示,他们已联系过的大多数软件供应商都在几天时间内修复了这个问题。

Java并非唯一一个受此漏洞影响的语言,但潜在的危害却是最大的。JavaScript的好处在于它的类库相对而言更集中化,并且它的两个具有解压缩文件功能的有风险的类库也已经修复了这个问题。.Net 生态中处理解压缩功能的类库也相对比较集中,在它的三个类库中已经有两个得到了修复,这两个发现了漏洞的库是 NuGet DotNetZip 与 SharpCompress。在 Go 生态系统中,mholt archiver 库发现了这一漏洞,但也已经修复。Snyk 的调查团队在 Ruby 和 Python 生态中还没有发现这一bug。

Snyk 在 GitHub 上的相关项目将会由 Snyk 自身与各社区项目维护者时刻更新最新进展,该项目包含了各编程语言生态系统中与这一漏洞相关的最新信息的完整列表。

查看英文原文:Zip Slip Directory Traversal Vulnerability Impacts Multiple Java Projects

[<img src=“https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/6/7/163d9f3bf2b2f5f0~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.image)]( “https://gmtc.geekbang.org/?utm_source=ending&utm_medium=infoq&utm_campaign=8zhe”” style=“margin: auto” />