、小白都能看懂的JSON反序列化远程命令执行

作者:CQITer小编 时间:2018-03-25 09:57

字号

Fastjson是一个由阿里巴巴维护的一个json库。它采用一种“假定有序快速匹配”的算法,是号称Java中最快的josn库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。今天我们就以最详细的姿势,一步步分析一下FastJson的远程命令执行!

0×01序列化

先熟悉一下FastJson的用法,毕竟连用法都不会怎么分析漏洞。下面用在最简单的示例快速入门一下FastJson

image.png

简单创建了一个实体bean,并set了两个属性值。进行简单的序列化,看看序列化后是不是变成了我们想要的东西。至于WriteClassName的作用,序列化时写入类型信息,默认为false。反序列化是需用到。

image.png

此时,已经非常完美的序列化成了我们常见的json数据。而加了WriteClassName属性的序列化,多了一个@type,也就是我们当时创建的那个实体对象。

0×02反序列化

反序列化的用法也比较简单,也就是将toJSONString换成parseObject即可。第一个参数是json字符串,第二个参数就是前面说到的@type实体对象。

image.png

成功的将字符反序列化位了实体对象。

image.png

0×03静态分析

分析漏洞最好的方式就是看看他到底做了什么防御,从他的补丁入手。

image.png

image.png

从更新的补丁来看,官方增加了一个checkAutoType方法,看到check这个词大概就能想到这块估计是是做了一个黑名单。跟进这个方法

image.png

发现checkAutoType方法对denyList列表进行了便利。跟进checkAutoType看一看。


public Class<?> checkAutoType(StringtypeName, Class<?> expectClass) {

if (typeName == null) {

return null;

}

final String className = typeName.replace('$', '.');

if (autoTypeSupport || expectClass != null) {

for (int i = 0; i < acceptList.length; ++i) {

String accept = acceptList[i];

if (className.startsWith(accept)){

returnTypeUtils.loadClass(typeName, defaultClassLoader);

}

}

for (int i = 0; i < denyList.length; ++i) {

String deny = denyList[i];

if (className.startsWith(deny)){

throw newJSONException("autoType is not support. " + typeName);

}

}

}

Class<?> clazz = TypeUtils.getClassFromMapping(typeName);

if (clazz == null) {

clazz = deserializers.findClass(typeName);

}

if (clazz != null) {

if (expectClass != null && !expectClass.isAssignableFrom(clazz)){

throw newJSONException("type not match. " + typeName + " -> " +expectClass.getName());

}

return clazz;

}

if (!autoTypeSupport) {

for (int i = 0; i < denyList.length; ++i) {

String deny = denyList[i];

if (className.startsWith(deny)){

throw newJSONException("autoType is not support. " + typeName);

}

}

for (int i = 0; i < acceptList.length; ++i) {

String accept = acceptList[i];

if(className.startsWith(accept)) {

clazz =TypeUtils.loadClass(typeName, defaultClassLoader);

if (expectClass != null&& expectClass.isAssignableFrom(clazz)) {

throw newJSONException("type not match. " + typeName + " -> " +expectClass.getName());

}

return clazz;

}

}

}

if (autoTypeSupport || expectClass != null) {

clazz = TypeUtils.loadClass(typeName, defaultClassLoader);

}

if (clazz != null) {

if (ClassLoader.class.isAssignableFrom(clazz) // classloader is danger

||DataSource.class.isAssignableFrom(clazz) // dataSource can load jdbc driver

) {

throw newJSONException("autoType is not support. " + typeName);

}

if (expectClass != null) {

if(expectClass.isAssignableFrom(clazz)) {

return clazz;

} else {

throw newJSONException("type not match. " + typeName + " -> " +expectClass.getName());

}

}

}

if (!autoTypeSupport) {

throw new JSONException("autoType is not support. " +typeName);

}

return clazz;

}

}

首先他会先判断expectClass是否为空如果为空的化,就会去检查denyList这个列表。看名字就知道是一个黑名单列表。看看这个列表里都有什么东西。

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接