Spring RCE远程执行漏洞(CVE-2022-22965)
这个洞22年3月底被大佬发现公布,由于Spring框架的影响范围太大了。复现条件又很低,本身就是高危的RCE漏洞可以直接拿到服务器的shell,像作者说的一样确实是一个核弹漏洞。
影响范围
JDK>8
Spring Framework<5.3.18
Spring Framework<5.2.20
条件
类对象中有get/set方法
Spring controller接口中有对象传入
漏洞原理
User类,有name和Department两个属性
public class User {
private String name;
private Department department;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
}
Department类具有name属性
public class Department {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
一会准备测试的接口,注意:其中并没有调用User的get/set方法
@Controller
public class UserController {
@RequestMapping("/testUser")
public @ResponseBody String testUser(User user) {
System.out.println("==testUser==");
return "OK";
}
}
打断点后DEBUG启动
携带参数请求该接口
http://localhost:8888/testUser?name=tpa&department.name=code
User对象没有调用get/set方法但其属性却有了值,这是因为Spring的参数绑定特性,而department.name则是多级绑定。(若department中也存在一个具备name属性的area对象,传入参数department.area.name其属性也会更改。)实际上department.name在后台的调用链路为
User.getDepartment() => Department.setName()
department.area.name则为
User.getDepartment() => Department.getArea() => Area.setName()
因为是封装类private私有属性,能更改类的属性不直接调用get/set肯定是通过反射了。而JDK自带的一个类PropertyDescriptor就可以通过反射来获取设置对象的属性。实现Spring框架参数绑定自动调用get/set方法的关键类BeanWrapperImpl就是对其进行的封装。
public class PropertyDescriptorTest {
public static void main(<