标签 Spring 下的文章

CVE-2018-1261: Unsafe Unzip with spring-integration-zip分析复现

开篇

日前,Spring的一个zip组件被爆了一个严重的漏洞,漏洞编号和标题为CVE-2018-1261 Unsafe Unzip with spring-integration-zip。根据描述在spring-integration-zip的1.0.1版本之前在对bzip2, tar, xz, war, cpio, 7z类型的压缩文件进行在解压的时候,如果压缩文件是恶意构造的不可信文件,可导致向任意目录写入文件。现在我们来复现和分析一下该漏洞的发生细节。

复现漏洞

为了复现漏洞,我们可以到Spring的GitHub下载存在漏洞版本的源码文件,地址:https://github.com/spring-projects/spring-integration-extensions/releases下载1.0.1之前的版本,然后在本地解压。

然后到spring-integration-zip目录下,使用命令:

./gradlew idea

生成idea的项目文件,执行完成后,即可用IDEA打开spring-integration-zip.ipr文件如下:

201805151526390164908264.png

根据描述,提到了

This specifically applies to the unzip transformer.

我们可以通过修改src/test/java/org.springframework.integration.zip/transformer文件下面的测试文件进行漏洞的复现和分析,

这个目录下面有这些文件:

201805151526390660203311.png

这里自带了2个测试类,分别是测试压缩和解压相关的。从漏洞描述里,我们大概可以猜到是在解压的压缩包文件里有文件名为:../../../../hack.txt这样的文件,在解压释放时将文件名直接和文件路径进行拼接,然后创建文件,因 ../../ 跳跃到了其他目录,文件被释放到了预期意外的目录下面从而导致了漏洞发生。

于是我们需要制作一个这样的“特殊”文件,这里可以通过ZipTransformerTests文件里的函数,加以修改来实现,修改测试代码如下:

201805151526391519652813.png

我们通过unzip命令看看压缩包文件的结构如下图:

201805151526391664308552.png

做好了压缩包后,下面是参考给出的测试方法,修改的解压代码截图如下:

201805151526393096305118.png

现在我们可以使用Junit运行这个测试函数,观察tmp目录,会生成txt文件,

201805151526393364145629.png

我们来调试看看,下断点跟进处理doZipTransform的实现代码里,如下图:

201805151526395851195117.png

这里的payload是MessageBuilder类的withPayload函数的参数,是一个输入流,读取加载的是我们给的zip文件

201805151526396199825873.png

下面是实现的是使用ZipUtil类遍历输入流里每一个Entry利用回调函数ZipEntryCallback处理它,

重点看处理的逻辑:

201805151526396871306660.png

继续跟进:

201805151526396973476088.png

文件成功释放到指定目录,如下截图:

201805151526397166529379.png

到此漏洞已经被成功利用,产生漏洞的原因是对压缩文件里的文件名没有任何过滤,直接进行文件路径+文件名的拼接,创建了新文件。

我们看看官方给的修复是怎样的,补丁地址,部分截图如下:

201805151526397427442105.png

首先删掉了直接拼接的代码,加入了一个checkPath函数,该函数代码如下:

201805151526397607951610.png

我们更新一下这块修复代码然后再次进行测试如下图:

201805151526398014190310.png

这里已经测试失败了,因为checkPath函数对destinationFile进行了判断,即判断了要写入的文件绝对路径值destinationFile.getCanonicalPath()函数是否包含了指定的释放目录,在这个下面

201805151526398279776249.png

这里很明显不满足,抛出异常程序终止了。

201805151526398450511120.png

想法很皮,实践测试中,发现似乎也不会出现想的那样,绕过了进行文件写入操作,报错如下:

201805151526399941396853.png

测试中发现更新了最新的补丁的现在(CVE-2018-1263补丁后),虽然不能任意目录跳了,但是可以在设置的workDirectory下面跳,最上层跳不出这个限制。

比如,制作压缩包:

201805161526401438177027.png

解压代码:

201805161526401424207075.png

解压后:

201805161526401517763498.png

这里举例说这个情况,是告诉大家配置不当会存在一定风险的,在配置workDirectory时尽量最小化配置,别配置成/var/ home/这一类的路径了,因为这些下面有一些地方被任意写入了文件是很可怕的。需要注意!!!

参考来源

CVE-2018-1259: XXE with Spring Data’s XMLBeam integration分析复现

前提

最近Spring几连发的漏洞里有一个漏洞是CVE-2018-1259,地址是https://pivotal.io/security/cve-2018-1259,根据我对描述的理解,这个锅不应该给Spring接啊,描述有一段话:

Spring Data Commons, versions prior to 1.13 to 1.13.11 and 2.0 to 2.0.6 used in combination with XMLBeam 1.4.14 or earlier versions contain a property binder vulnerability caused by improper restriction of XML external entity references as underlying library XMLBeam does not restrict external reference expansion.

描述中说Spring 的公用数据组件的1.13 到 1.13.11版本和2.0到2.0.6版本使用了XMLBeam 1.4.14 或更早的版本,它存在一个外部实体应用即XXE漏洞。问题出在XMLBeam身上,修复方式就是升级XMLBeam到1.4.15以上,这个锅Spring不应该背吧。

复现XMLBeam的XXE漏洞和分析

这个CVE应该给XMLBeam的,但是它的下载地址是https://xmlbeam.org/download.html,我们在GitHub找了一个使用XMLBeam的demo来进行漏洞复现和分析。

Demo地址:

https://github.com/olivergierke/spring-examples/tree/master/scratchpad/src

下载然后导入IDEA:

201805131526218553238503.png

这个Demo代码有点小情况需要处理才能很好的跑起来,导入IDEA后,用Maven开始构建。在site使用插件运行时,它使用的是Jetty组件运行,这个情况就是怎么访问uri地址/customers 都是404,一直很纳闷。在折腾中,我发现用junit测试是OK的,能复现和调试漏洞。后来同事提到用Spring-boot运行就很OK。于是这里记录一下怎么改用Spring-Boot运行(现学现用)。

201805131526218961914670.png

在上面的那个位置,添加SpringBoot启动代码,现在我们就可以右键直接run了。

201805131526219085500949.png

现在我们可以简单阅读demo代码,理解如何测试,找到XmlBeamExample.java文件如下:

201805131526219173589965.png

看看pom.xml确认一下XMLBeam的版本,用的是老版本1.4.6,目前最新的版本是1.4.14.

201805131526219445699743.png

环境准备好了,我们开始下断点,和构造测试的POST请求,构造POC如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [<!ELEMENT foo ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<user>
    <firstname>&xxe;</firstname>
    <lastname></lastname>
</user>

根据代码,我们需要构造POST请求,构造一组参数,XMLBeam会根据参数map对应进行自动解析绑定。

先复现一下效果:

201805131526220995310268.png

这个漏洞的根本原因是由于XMLBeam的用法不当,我们在XMLBeamd 库里找到创建XML解析实体对象的地方,如下截图:

201805151526355342895156.png

上面的是1.4.6版本,从官方下载最新的1.4.14版本的jar包源码看看,同样存在问题的,如下截图:

201805151526355503355930.png

官方目前没有挂出更新后的版本,在maven仓库里我们可以搜到,已经有里修复版本1.4.15,地址:http://mvnrepository.com/artifact/org.xmlbeam/xmlprojector 下载最新的版本后,再查看此处配置如下:

201805151526355686183890.png

一些配置项如下:

201805151526355798781702.png

从更新的代码来看,已经使用了开发语言提供的禁用外部实体的方法修复了这个XXE漏洞。

Spring官方的修复方式也是更新了这个库到1.4.15版本,

https://jira.spring.io/browse/DATACMNS-1311?jql=project%20%3D%20DATACMNS%20AND%20fixVersion%20%3D%20%221.13.12%20(Ingalls%20SR12)%22

收获

  1. 关于如何安全的使用和解析XML文本,可以看看下面给的参考文
  2. 知道了Spring Boot的这种启动方式,Jetty的坑,更加发现了Maven+IDEA配合的强大

参考

CVE-2018-1270 Remote Code Execution with spring-messaging

影响版本

  • Spring Framework 5.0 to 5.0.4
  • Spring Framework 4.3 to 4.3.14

漏洞分析

Spring Framework通过spring-messageing模块和STOMP代理对象通讯。根据漏洞描述可以知漏洞出现在spring-message模块 或者是 stomp-websockets模板块,下面逐一分析:

spring-websockets 模块

存在的敏感方法

@Nullable

public String[] decode(String content) throws IOException {
return (String[])this.objectMapper.readValue(content, String[].class);
}

反序列化使用的jackson组件,但是没有开启autotype功能,并且代码指定了反序列化类型为String[].class,利用jndi注入方式会导致异常,没有成功。

625fbd72201477f4d64f9b4a2e79a5a1.png

分析spring-message模块

DefaultSubscriptionRegistry类中方法addSubscriptionInternal存在expression = this.expressionParser.parseExpression(selector)(危险的SPEL表达式语句)。
根据上下文可以初步判定selector参数可以控制,但是了解SPEL注入的同学应该知道,要想达到代码执行,需要调用expression.getValue()或者expression.setValue()方法。继续寻找会发现该文件的154-164行调用了expression对象的getValue方法。

复现下漏洞的触发流程:

点击Connet按钮抓包

52b29eca6c5ea5429201c48c8ad96bee.png

修改请求报文,插入如下字段

\nselector:new java.lang.ProcessBuilder("/Applications/Calculator.app/Contents/MacOS/Calculator").start()

43ec3a11b117e9b86582d16d1922fc13.png

回到聊天窗口,发送任意消息即可触发恶意代码

c25b1fe4957ce9fcd465d867e1d010df.png

9d57f7cb1ad30ab1e747922601163798.png

586b85fa87889b1950535a76e5c25553.png

修复方案

  • 5.0.x users should upgrade to 5.0.5
  • 4.3.x users should upgrade to 4.3.15

漏洞二:xss vul in gs-messaging-stomp-websocket demo

2f1a64a5f7f2e688198fc8ffe5d805eb.png

Patch:https://github.com/spring-guides/gs-messaging-stomp-websocket/commit/6d68143e04ea1482b724c3f620688ec428089bc0

From:https://pivotal.io/security/cve-2018-1270

CVE-2016-5007 Spring Security / MVC Path Matching Inconsistency

概要

  • 产品名称:Spring Web + Spring Security / Spring Boot
  • 标题:Spring Security / MVC Path Matching Inconsistency
  • CVE ID: CVE-2016-5007
  • Intrinsec ID:ISEC-V2016-01
  • 风险级别:中
  • 漏洞利用:远程
  • 影响:请求授权绕过

描述

此漏洞影响的Spring Web和Spring Security使用HttpSecurity.authorizeRequests用于URL访问控制的应用。

Spring提供了一个Spring Security使用文档:

http://docs.spring.io/spring-security/site/docs/current/reference/html/jc.html#authorize-requests

protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()                                                                
            .antMatchers("/resources/**", "/signup", "/about").permitAll()                  
            .antMatchers("/admin/**").hasRole("ADMIN")                                      
            .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")            
            .anyRequest().authenticated()                                                   
            .and()
        // ...
        .formLogin();
}

在以下示例中,用户”User”不是管理员,并且无法访问”/admin/”管理目录:

cve-2016-5007-1.png

但是,如果在URL中将空格(或其他空格字符)附加到”admin”前后,可以轻易绕过安全过滤器。

  • 附加空格(由浏览器自动编码为”%20″):

cve-2016-5007-2.png

  • %0D前置:

cve-2016-5007-3.png

问题是使用不同的匹配器来实现访问控制,并且识别哪个控制器类应该处理请求。用于访问控制的第一个匹配器是严格的:”admin “被认为不同于”admin”:

cve-2016-5007-4.png

然而,用于找到适当的控制器的第二匹配器应用删除每个URL令牌之前和之后的空白的修剪操作,因此”admin”变为”admin”:

cve-2016-5007-5.png

总之:

访问控制匹配器不识别受保护的路径,因此应用默认的“允许”规则,而控制器查找器匹配器找到受保护的控制器。

两个匹配器之间的严格性不匹配导致了这种情况。

这个漏洞危害性高低与否取决越权查看页面后查询数据的时候是否有校验当前用户的session。

影响版本

  • Spring Security 3.2.x,4.0.x,4.1.0
  • Spring框架3.2.x,4.0.x,4.1.x,4.2.x
  • 其他不受支持的版本也会受到影响

解决方案

Spring Security提供了可以将模式匹配委派给Spring框架的URL授权,要利用这个选项,应用程序应该升级到Spring Security 4.1.1+和Spring Framework 4.3.1+并使用MvcRequestMatcher。

Spring Framework 3.2.x,4.0.x,4.1.x,4.2.x的用户可以使用MVC Java配置或MVC命名空间将AntPathMatchertrimTokens属性设置为“false”。

此外,应用程序应该总是使用Spring Security的一种机制(例如添加@Secured注释),在应用程序的业务层使用额外的授权来补充基于URL的授权。

分享一个两年前的测试案例:

目标是基于拦截器的访问控制,但是系统做拦截判断的时候是采用完全匹配模式校验,所以可以轻易绕过。

http://xxx.com:8000/security/security!admin.action --blocking
http://xxx.com:8000////security/security!admin.action --bypass

简单总结下这个两个漏洞产生的原因:

第一个案例的问题问题出现在第二个规则检测前的数据处理工作,do_work(a)的时候已经不知道do_check(a)是什么内容了!这里能做什么?只能保证保持输入a不变,能做事就做,做不了就反馈错误!此类问题绝非个案,平时代码审计可以多加关注。

Reference