一、什么是Bean
实体类通常如下定义,一般一个实体类属性对应一个数据库表的结构,加上set和get方法
public class Student {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Holle [str=" + str + "]";
}
}
在spring框架中如何实例化呢,spring框架是配置地狱,在其配置文件xml中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--在Spring中创建对象,在Spring这些都称为bean
类型 变量名 = new 类型();
Hello hello = new Hello();
bean = 对象(hello)
id = 变量名(hello)
class = new的对象(new Hello();)
property 相当于给对象中的属性设值,让str="Spring"
-->
<bean id="hello" class="pojo.Hello">
<property name="str" value="Spring"/>
</bean>
</beans>
结论:bean其实是实体类的对象。
二、什么是Spring-mvc依赖注入(DI)
建议bilibili看下狂神的java视频,spring依赖注入
实体类
public class User {
private int id;
private String name;
private int age;
//构造
//get/set
//tostring()
}
处理方法
@Controller
public class ControllerTest2{
@RequestMapping("/user")
public String user(User user){
System.out.println(user);
return "hello";
}
}
提交数据 : http://localhost:8080/mvc04/user?name=kuangshen&id=1&age=15
后台输出 : User { id=1, name='kuangshen', age=15 }
当我们提交参数时,Springmvc依靠反射机制给user bean属性赋值
三、payload调试
当传入恶意 http://localhost:8080/mvc04/user?class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
调用栈如下doDispatch方法是Controller入口函数,BeanWrapperImpl是具体bean参数绑定实现类
setValue:334, BeanWrapperImpl$BeanPropertyHandler (org.springframework.beans)
processLocalProperty:458, AbstractNestablePropertyAccessor (org.springframework.beans)
setPropertyValue:278, AbstractNestablePropertyAccessor (org.springframework.beans)
setPropertyValue:266, AbstractNestablePropertyAccessor (org.springframework.beans)
setPropertyValues:97, AbstractPropertyAccessor (org.springframework.beans)
applyPropertyValues:848, DataBinder (org.springframework.validation)
doBind:744, DataBinder (org.springframework.validation)
doBind:197, WebDataBinder (org.springframework.web.bind)
bind:107, ServletRequestDataBinder (org.springframework.web.bind)
bindRequestParameters:157, ServletModelAttributeMethodProcessor (org.springframework.web.servlet.mvc.method.annotation)
resolveArgument:160, ModelAttributeMethodProcessor (org.springframework.web.method.annotation)
resolveArgument:127, HandlerMethodArgumentResolverComposite (org.springframework.web.method.support)
getMethodArgumentValues:167, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:134, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:104, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:892, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:797, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:1039, DispatcherServlet (org.springframework.web.servlet)
doService:942, DispatcherServlet (org.springframework.web.servlet)
processRequest:1005, FrameworkServlet (org.springframework.web.servlet)
doGet:897, FrameworkServlet (org.springframework.web.servlet)
service:655, HttpServlet (javax.servlet.http)
service:882, FrameworkServlet (org.springframework.web.servlet)
service:764, HttpServlet (javax.servlet.http)
internalDoFilter:231, ApplicationFilterCh
先循环读取传出的key值,如下两张图
下一步,获取value值
以之前的key值作为的Bean属性,去找对应的bean
最终反射调用方法赋值,从反射方法可以看出是日志配置相关的
自查方案
目前exp具体影响不明,因为一个完美的武器级exp需要满足
-
必须要能通过class为起始对象获取到引用(深度搜索的起点为class),并且还要有无参get方法
-
必须有get/set方法,符合java bean规范。
-
set方法的值必须为字符串
-
该controller必须存在spring的参数绑定。
目前只流传tomcat的exp,不排除其他中间件的exp,不排除dos等其他漏洞的exp。
waf规则
现在我们知道为什么java9可以而java8不可以的原因,所以我们可以断定class.module
这串字符串一定出现在exp的请求中,可以重点防御这串字符串
甲方自查手册
-
确定线上业务中的controller是否使用了spring的参数绑定技术,如果使用则按照下一条继续排查
-
jdk版本是否为jdk9以上,jdk8以下天然防御
因为该漏洞的本质是变量覆盖漏洞,但是利用手法通过覆盖tomcat的配置修改tomcat的日志位置到根目录,修改日志的后缀为jsp去getshell。
-
如果防止getshell,则重点排查中间件是否为tomcat。
-
非tomcat中间件目前来说不一定会被getshell,但是存在被该漏洞影响到线上业务的风险(任意变量覆盖到中间件的其他变量配置,导致dos等其他场景),建议停机修改应用,修复方式如下
注意,目前只有通过应用下线重发布的方式打补丁,并且非spring官方推荐修复,存在一定几率的翻车风险。同时按以下两个步骤进行漏涧的临时修复:
1.在应用中全局搜索@InitBinder注解,看看方法体内是否调用dataBinder.setDisallowedFields方法,如果发现此代码片段的引入,则在原来的黑名单中,添加{"class.","Class. *","*. class.", ".Class."}。(注:如果此代码片段使用较多,需要每个地方都追加)
在应用系统的项目包下新建以下全局类,并保证这个类被Spring 加载到(推荐在Controller 所在的包中添加).完成类添加后,需对项目进行重新编译打包和功能验证测试。并重新发布项目。
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
@ControllerAdvice
@Order(10000)
public class a{
@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
String[] abd = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
dataBinder.setDisallowedFields(abd);
}
}
参考:https://mp.weixin.qq.com/s/bG3BCdM-suCZldN7FIpYqw
原文始发于微信公众号(瑞不可当):Spring rce漏洞分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论