一. 漏洞利用条件
jdk9+
Spring 及其衍生框架
使用tomcat部署spring项目
使用了POJO参数绑定
Spring Framework 5.3.X < 5.3.18 、2.X < 5.2.20 或者其他版本
二. 漏洞分析
通过API Introspector. getBeanInfo 可以获取到POJO的基类Object.class的属性class,进一步可以获取到Class.class的其他属性,其中就包括了classloader,再利用获取到的属性构造利用链,这次爆出来的漏洞既然是绕过,那么原理应该也差不多,首先先搭建环境,构造一个简单的POJO:
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
再写个简单的controller:
@RequestMapping("/test")
public String test(User user){
System.out.println(user.getName());
return "hello spring-mvc";
}
发送get请求:http://localhost:8080/test?name=test
即可完成一次简单的数据绑定。
在开始调试分析之前,首先需要对spring的数据绑定体系机构有个简单的了解,其中涉及到一个关键类org.springframework.validation.DataBinder类,DataBinder类实现了TypeConverter和PropertyEditorRegistry接口,作用主要是把字符串形式的参数转换成服务端真正需要的类型的转换,同时还有校验功能,其中有如下这些属性:
@Nullable
private final Object target;//需要数据绑定的对象
private final String objectName;//给对象起得名字默认target
@Nullable
private AbstractPropertyBindingResult bindingResult;//数据绑定后的结果
@Nullable
private SimpleTypeConverter typeConverter;//当target!=null时不会用到
private boolean ignoreUnknownFields = true;//忽略target不存在的属性,作用于PropertyAccessor的setPropertyValues()方法
private boolean ignoreInvalidFields = false;//忽略target不能访问的属性
private boolean autoGrowNestedPaths = true;//当嵌套属性为空时,是否可以实例化该属性
private int autoGrowCollectionLimit = DEFAULT_AUTO_GROW_COLLECTION_LIMIT;//对于集合类型容量的最大值
@Nullable
private String[] allowedFields;//允许数据绑定的资源
@Nullable
private String[] disallowedFields;//不允许的
@Nullable
private String[] requiredFields;//数据绑定必须存在的字段
@Nullable
private ConversionService conversionService;//为getPropertyAccessor().setConversionService(conversionService);
@Nullable
private MessageCodesResolver messageCodesResolver;//同bindingResult的
private BindingErrorProcessor bindingErrorProcessor = new DefaultBindingErrorProcessor();
private final List<Validator> validators = new ArrayList<>();//自定义数据校验器
其中bindingResult是BeanPropertyBindingResult的实例,内部会持有一个BeanWrapperImpl。
bind()是数据绑定对象的核心方法:将给定的属性值绑定到此绑定程序的目标,源码如下:
**public**void bind(PropertyValues pvs) {
MutablePropertyVal