javajson格式字符串转为map_【⼲货】Java反序列化漏洞总
1
前⾔
什么是序列化和反序列化
Java 提供了⼀种对象序列化的机制,该机制中,⼀个对象可以被表⽰为⼀个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。反序列化就是通过序列化后的字段还原成这个对象本⾝。但标识不被序列化的字段是不会被还原的。
序列化有什么⽤
1)⽹站相应的session对象存储在硬盘上,那么保存在session中的内容就必须实现相关的序列化操作。
2)如果使⽤的java对象要在分布式中使⽤或者在rmi远程调⽤的⽹络中使⽤的话,那么相关的对象必须实现java序列化接⼝。
2
Java反序列化类型
我们最常见就是原⽣的java反序列化类型,其实java中有⼏种⽅式可以执⾏反序列化,本⽂⽬的也是对这⼏种类型的反序列化⽅法进⾏归纳和总结。
1、Java原⽣序列化
Java包中⾃带的类InputStream和OutputStream,它们之间可以互相转化,使⽤writeObject序列化,使⽤readObject反序列化。【代码⾏请左右滑动查看全部内容】
import java.io.*;
public class DeserializeDemo
{
public static void main(String [] args)
{
Employee e = null;
try
{
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
}catch(IOException i)
{
i.printStackTrace();
return;
}catch(ClassNotFoundException c)
{
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
2、Json序列化
Json序列化⼀般会使⽤jackson包,通过ObjectMapper类来进⾏⼀些操作,⽐如将对象转化为byte数组或者将json串转化为对象。
public static String serialize(T t) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
String jsonResult = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(t);
return jsonResult;
}
3、Fastjson反序列化
Fastjson是⼀个性能很好的Java语⾔实现的Json解析器和⽣成器,由来⾃阿⾥巴巴的⼯程师开发。具有极快的性能,超越任何其他的Java Json Parser。Fastjson使⽤parseObject来进⾏反序列化。
import com.alibaba.fastjson.JSON;
public class Person {
int age;
String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
String jsonString="{\"name\":\"hah\",\"age\":1}";
Person person = JSON.parseObject(jsonString, Person.class);
System.out.println(1);
}
}
4、Protobuf 反序列化
Protocol Buffers 是⼀种轻便⾼效的结构化数据存储格式,可以⽤于结构化数据串⾏化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可⽤于通讯协议、数据存储等领域的语⾔⽆关、平台⽆关、可扩展的序列化结构数据格式。⽬前提供了 C++、Java、Python 三种语⾔的 API。
proto.proto⽂件内容
package proto;
message TestMsg{
optional string id = 1;
optional string name = 2;
}
序列化
public byte[] build(){
Proto.TestMsg.Builder builder = wBuilder();
builder.setId("ID的值");
builder.setName("Name的值");
Proto.TestMsg msg = builder.build();    ByteArray();
}
反序列化
Proto.TestMsg msg = Proto.TestMsg.urnByte());
System.out.Println(msg);
3
各类反序列化⽐较
4
反序列化漏洞简介
除了使⽤protobuf进⾏反序列化没有出现过漏洞,其他⽅式的序列化都曾出现过漏洞。下⾯将简单介绍下漏洞,详细的漏洞和exp构造⽅法⼤家可以去⽹上搜索关键字查看(java⼏个反序列化漏洞exp构造过程都⼗分精彩,推荐⼤家认真阅读下)
1、Object Serialize 漏洞
Apache Commons Collections中实现了TransformedMap ,该类可以在⼀个元素被添加/删除/或是被修改时(即key或value:集合中的数据存储形式即是⼀个索引对应⼀个值,就像⾝份证与⼈的关系那样),会调⽤transform⽅法⾃动进⾏特定的修饰变换。
TransformedMap.decorate⽅法,预期是对Map类的数据结构进⾏转化,该⽅法有三个参数。
第⼀个参数为待转化的Map对象
第⼆个参数为Map对象内的key要经过的转化⽅法(可为单个⽅法,也可为链,也可为空)
第三个参数为Map对象内的value要经过的转化⽅法
通过对第三个参数通过构造ChainedTransformer链,通过⼀系列变化,最终执⾏系统命令。
2、Jackson-databind 漏洞
python转java代码Jackson是⼀套开源的java序列化与反序列化⼯具框架,可将java对象序列化为xml和json格式的字符串及提供对应的反序列化过程。由于其解析效率较⾼,⽬前是Spring MVC中内置使⽤的解析⽅式,该漏洞的触发条件是ObjectMapper反序列化前调⽤了enableDefaultTyping⽅法。该⽅法允许json字符串中指定反序列化java对象的类名,⽽在使⽤Object、Map、List等对象时,可诱发反序列化漏洞,导致可执⾏任意命令。
3、FastJson 漏洞
fastjson在解析json的过程中,⽀持使⽤autoType来实例化某⼀个具体的类,并通过json来填充其属性值。⽽JDK⾃带的类
apache.xalan.ax.TemplatesImpl中有⼀个私有属性_bytecodes,其部分⽅法会执⾏这个值中包含的Java 字节码。通过注⼊恶意代码到_bytecode,导致任意代码执⾏漏洞。
注:Fastjson和Jackson Payload构造的⽅式都⼀样,虽然解析函数不⼀样,但是都是将json转为object,过程是类似的。
5
阻⽌反序列化漏洞
1、Java Serialization
jdk⾥增加了⼀个filter机制
这个⼀开始是出现在jdk9上的,后⾯移值回jdk6/7/8上,如果安装的jdk版本是⽐较新的,可以到相关的类
Oracle打算废除java序列化:
2、jackson-databind
jackson-databind⾥是过滤掉⼀些已知的类,参见SubTypeValidator.java
jackson-databind的CVE issue列表
3、fastjson
fastjson通过⼀个denyList来过滤掉⼀些危险类的package,参见ParserConfig.java
fastjson在新版本⾥denyList改为通过hashcode来隐藏掉package信息,但通过这个DenyTest5可以知道还是过滤掉常见危险类的package
fastjson在新版本⾥默认把autoType的功能禁⽌掉了
这些序列化漏洞的根本原因是:没有控制序列化的类型范围。
仔细看的读者会发现并没有提及protobuf的反序列化漏洞,为什么在protobuf⾥并没有这些反序列化问题?
protobuf在IDL⾥定义好了package范围
protobuf的代码都是⾃动⽣成的,怎么处理⼆进制数据都是固定的
protobuf把⼀切都框住了,少了灵活性,⾃然就少漏洞。
注:IDL(Interface description language)⽂件:参与通讯的各⽅需要对通讯的内容需要做相关的约定(Specifications)。为了建⽴⼀个与语⾔和平台⽆关的约定,这个约定需要采⽤与具体开发语⾔、平台⽆关的语⾔来进⾏描述。这种语⾔被称为接⼝描述语⾔(IDL),采⽤IDL撰写的协议约定称之为IDL⽂件。
6
总结
本⽂总结了java反序列化的⼏种⽅式,并回顾了java⼏个经典的
漏洞以及对应的修复⽅案,希望通过本⽂,⼤家对java反序列化漏洞有更深刻的认知。
参考链接:
⼀审Akuma/⼆审viga

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。