Fastjson 1.2.9
com/alibaba/fastjson/parser/ParserConfig.class 中其实增加了一个 denyList:
因此不能用 @type 反序列化 java.lang.Thread 类
Fastjson 1.2.22 - 1.2.24
可利用链为 com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl, fastjson
在反序列化该类的过程中会调用 getOutputProperties 方法,并在 getTransletInstance
方法的执行过程中读取 _bytecodes 属性中的字节码加载类,关键代码如下:
可见 poc 需要设置 _name 属性,且恶意类要继承 AbstractTranslet 以便初始化,比如:
poc:
在 1.2.25 版本中引入了 checkAutoType 安全机制,通过对 @type 中的类进行黑名单和白
名单检测来过略恶意类
commit: https://github.com/alibaba/fastjson/commit/90af6aadfa9be7592fdc8e174458ddaebb2b19c4
Fastjson 1.2.41
出现对 1.2.25 版本 checkAutotype 机制的绕过:利用 JNI 字段描述符绕过黑名单检查,
只需要在全限定类名前后分别加上 L 和 ;
poc:
Fastjson 1.2.42
黑名单进行了加密混淆:https://github.com/LeadroyaL/fastjson-blacklist
另外 checkAutotype 方法也对类名进行了额外检测,如果是 Lcom.xxx;
的形式会先删除首尾
字符再判断是否在黑名单中。但可以通过双写绕过:
Fastjson 1.2.43
修复了 1.2.42 的双写绕过,但是可以用 [
绕过(在 JNI 字段描述符中表示数组层数)
如果仅仅增加一个 [
, fastjson 在解析时会报错,为了顺利反序列化还需要根据报错调整
poc,最终 poc 如下:
这个利用链属于 JNDI Bean Property, 在执行 setAutoCommit 方法时调用了
InitialContext#lookup 来加载远程类,相较于 TemplatesImpl, 不需要开启
SupportNonPublic
当然除了 json poc 还需要一个恶意 LDAPServer 和一个恶意类,可以使用 mbechler/marshalsec
Fastjson 1.2.45
漏洞产生原因很简单,就是利用了黑名单中没有的类——mybatis 库中的
JndiDataSourceFactory 类
poc:
Fastjson 1.2.47
这版本漏洞的利用链依然是 com.sun.rowset.JdbcRowSetImpl, 但是 poc 的构造方法不同,
可以在不开启 AutoTypeSupport 的情况下使用并绕过 checkAutoType 的黑名单检查
poc:
可以看出这次的 poc 比之前多了一部分,这样构造的原因是 checkAutoType 在进行黑白名
单检查之前,会尝试从 mappings 变量中获取一些基础类,以便于在反序列化这些基础类时
提高效率
首先 fastjson 反序列化 poc 的 a 部分,checkAutoType 将返回 JdbcRowSetImpl 类的
class 对象。在后续调用 MiscCodec#deserialze 方法时,会尝试获取 json 中的 val 属
性,也就是 com.sun.rowset.JdbcRowSetImpl, 而如果反序列化的是 Class 对象,则调用
TypeUtils#loadClass 将 val 指示的类加入到 mappings 集合中
然后 fastjson 反序列化 poc 的 b 部分,按理来说 com.sun.rowset.JdbcRowSetImpl 会被
checkAutoType 的黑名单检测到,但因为这时候 JdbcRowSetImpl 类信息已经保存到
mappings 中了,checkAutoType 在进行黑名单检测前便从 mappings 中拿到类,从而跳过
了检测,顺利反序列化
详细分析:Fastjson 1.2.47 漏洞分析
Fastjson 1.2.59
fastjson 对转义字符 \x 的处理不当,导致 dos 漏洞
poc:
Fastjson 1.2.60
存在两个不在 checkAutoType 黑名单中的三方类可以被利用
- org.apache.commons.configuration.JNDIConfiguration
- oracle.jdbc.connector.OracleManagedConnectionFactory
都是基于 JNDI 进行代码执行,需要恶意 RMIServer
Fastjson 1.2.62
无条件的 re-dos 漏洞,即正则表达式导致的 dos 漏洞
poc1:
poc2:
Fastjson 1.2.68
这次漏洞围绕 checkAutoType 中的 expectClass 参数——当 expectClass 参数不为 Null、且当
前需要实例化的类型是 expectClass 的子类或实现时会将传入的类视为一个合法的类(此类
不能在黑名单中)
下面结合 checkAutoType 的部分代码来看一下在哪些情况下可以通过校验进行反序列化:
总结一下,在以下情况可以通过 checkAutoType 的校验:
- 白名单的类
- 开启了 autoType 且类不在黑名单中
- 使用了 JSONType 注解
- 设置了 expectClass, 当前类是它的子类
- mappings 中的类,通常是一些预设的基础类和缓存的类
在上述限制中,有不少第三方库给挖掘出可以利用的链,我们分析一下
sun.rmi.server.MarshalOutputStream 这个利用链,通过它可以进行任意文件写入
poc:
首先检查 AutoCloseable 类,由于该类在 mappings 集合中,通过 getClassFromMapping
即可获取
AutoCloseable 是接口类,fastjson 继续读取并检查后续的
sun.rmi.server.MarshalOutputStream, 并把 AutoCloseable 作为 expectClass 传入
通过黑白名单等一系列检查后来到下面的判断,此时 expectClassFlag 为 true, 加载了
MarshalOutputStream 类
此时 clazz 不为空,且 MarshalOutputStream 继承了 AutoCloseable 接口,在下图的红
框中返回,避免了后续检查 autoTypeSupport 属性,因此在关闭 autoType 的情况下仍然
可以利用
后续就不深入分析 MarshalOutputStream 这条链的反序列化过程了,除了这个 poc 还有其
他利用第三方库构造的 poc, 大致上都是利用了 AutoCloseable 这个在 mappings 中的类,
再结合 expectClass 属性从它的子类中去挖掘利用链
任意写文件:
commons-io 2.0-2.6:
commons-io 2.7-2.8: