各版本 payload 复现
https://github.com/safe6Sec/ShiroAndFastJson
判断是否用了 fastjson
鉴别 fastjson
DNSLOG
根据解析变化
根据响应状态
鉴别 org.json
特殊字符
鉴别 gson
浮点类型精度丢失
注释符
鉴别 jackson
浮点类型精度丢失
注释符
不支持单引号作为界定符
多余的类成员
如果目标回显详细报错信息,稍微破坏一下 json 结构,比如多一个{,比如简简单单把{}变成 a。就可以看出来到底是不是 jackson。
如果目标不回显详细报错信息,而是只有一个 500 或者 error,那么 jackson 不允许存在不相关的键值,fastjson 允许这个特性就可以派上用场了。
比如原 json 如下。
加上一个不相关的键值
jackson 就会报错,fastjson 则不会,而是和之前一模一样。
版本探测
无报错信息探测
https://mp.weixin.qq.com/s/jbkN86qq9JxkGNOhwv9nxA
【不报错】1.2.83/1.2.24 【报错】1.2.25-1.2.80
【不报错】1.2.24-1.2.68 【报错】1.2.70-1.2.83
【不报错】1.2.24-1.2.47 【报错】1.2.48-1.2.83
【不报错】1.2.24 【报错】1.2.25-1.2.83
延迟探测
原理同 ssrf 漏洞。请求本机已开放端口不延时,请求不开放的端口则延时。
fastjson 1.1.15-1.2.24
通用 payload,可用于 parseObject 的场景
fastjson 1.2.9-1.2.47
通用 payload,可用于 parseObject 的场景
Fastjson 1.2.36 - 1.2.62
利用正则 dos 洞,进行探测。逐步加 a,直到延迟为止
参考https://mp.weixin.qq.com/s/5mO1L5o8j_m6RYM6nO-pAA
异常回显
异常回显 fastjson 精确版本号
dns 探测
主要是利用各个类被加入黑名单的方式进行判断,但此方法准确性不高。
原理重点关注 MiscCodec 处理时会去 nwe
URL,然后通过后面的 map#put 触发计算 key 的 hash。学习 urldns 链容易理解。
fastjson <1.2.43
fastjson <1.2.48
fastjson <1.2.68
精确探索 autoType 是否开启,开启后能打更多 payload
https://github.com/pen4uin/awesome-java-security/tree/main/alibaba%20fastjson
关键 rce 版本探测
1.2.24 版本,用上面的延时探测即可
1.2.47 版本
1.2.68 版本
1.2.80 版本探测 如果收到了两个 dns 请求,则证明使用了 1.2.83 版本
如果收到了一个 dns 请求,则证明使用了 1.2.80 版本
探测环境
- org.springframework.web.bind.annotation.RequestMapping
- org.apache.catalina.startup.Tomcat
- groovy.lang.GroovyShell
- com.mysql.jdbc.Driver
- java.net.http.HttpClient
如果系统存在这个类,会返回一个类实例,如果不存在会返回 null
通过使用 Character 将报错回显在 message 中
通过使用 DNSLOG 来探测依赖库
文件写,结合 commons-io 代码(stream 里面写 68 的 payload)
aspectj + ognl 任意文件读取 + DNSLOG 回显 打入白名单
aspectj + ognl 文件读取加 DNSLOG 回显
commons-io + ognl + URLReader 单字节文件读取(回显情况观察数值)
commons-io + ognl + URLReader 单字节文件读取(报错布尔)
commons-io + ognl + URLReader 单字节文件读取 HTTPLog
布尔回显(错误的时候有 log,正确时 无 log)
aspectj 读文件 + Character 报错回显
commons-io + ognl + URLReader + aspectj HTTP Log 回显
groovy 远程类加载
加白名单
远程类加载
利用链挖掘
https://xz.aliyun.com/t/7482
https://xz.aliyun.com/t/7789#toc-4
主要用 codeql 进行挖掘
FastJson 与原生反序列化
https://y4tacker.github.io/2023/03/20/year/2023/3/FastJson%E4%B8%8E%E5%8E%9F%E7%94%9F%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/
利用 fastjson 调用 get、set 的特性,构造出新的反序列化利用链。
fastjson2
各版本利用
除了考虑 Fastjson 版本,还得考虑 JDK 版本,中间件版本,第三方依赖版本。
JDK 版本对于 JDNI 注入的限制,基于 RMI 利用的 JDK 版本⇐6u141、7u131、8u121,基于 LDAP 利用的 JDK 版本⇐6u211、7u201、8u191。(更高版本也有绕过)
更高版本绕过可用https://github.com/veracode-research/rogue-jndi
- jndi
- JdbcRowSetImpl
- C3p0#JndiRefForwardingDataSource
- JndiDataSourceFactory
- bcel
- tomcat#dbcp
- ibatis
- TemplatesImpl
Fastjson 1.2.22-1.2.24
JdbcRowSetImpl
c3p0#JndiRefForwardingDataSource
JdbcRowSetImpl 无法成功可以一试
shiro#JndiObjectFactory
shiro#JndiRealmFactory
bcel
可用于解决不出网利用。 需要注意在 Java 8u251 以后,bcel 类被删除。
tomcat7
org.apache.tomcat.dbcp.dbcp.BasicDataSource
tomcat8 及其以后
org.apache.tomcat.dbcp.dbcp2.BasicDataSource
Poc
exp
执行命令回显.
1.2.33 ⇐ fastjson ⇐ 1.2.47
1.2.33⇐fastjson⇐12.36
1.2.37⇐fastjson⇐1.2.47
其他
TemplatesImpl
利用条件苛刻,可用于解决不出网利用。
需要调用=parseObject()=方法时,加入 Feature.SupportNonPublicField 参数。
_bytecodes 要进行 base64 编码
c3p0#WrapperConnectionPoolDataSource
可用于解决不出网利用。
fastjson <1.2.47
利用 c3p0 二次反序列化 cc payload 到达回显。
Fastjson 1.2.25-1.2.41
1.2.25 后将 TypeUtils.loadClass 替换为 checkAutoType()函数,增加了黑名单和白名单。
把 autoTypeSupport 默认为 False。
当 autoTypeSupport 为 False 时,先黑名单过滤,再白名单过滤,若白名单匹配上则直接加载该类,否则报错。
当 autoTypeSupport 为 True 时,先白名单过滤,匹配成功即可加载该类,否则再黑名单过滤。
1.2.25 黑名单
exp
条件需要开启 autotype
类名前面加了一个 L,后面加一个;可以绕过黑名单
Fastjson 1.2.25-1.2.42
从 1.2.42 版本开始,把之前的明文黑名单,改为 hash 黑名单。
如下大佬整理的
https://github.com/LeadroyaL/fastjson-blacklist
exp
条件需要开启 autotype
双写绕过
Fastjson 1.2.25-1.2.43
exp
条件需要开启 autotype
加[{绕过
Fastjson 1.2.25-1.2.45
条件需要开启 autotype
45 把之前问题修了,但是可以借助第三方组件绕过。
需要 mybatis,且版本需为 3.x.x 系列<3.5.0 的版本。
Fastjson1.2.25-1.2.47 通杀
借助缓存进行通杀,缓存在 1.2.48 被改为默认关闭
漏洞原理是通过 java.lang.Class,将 JdbcRowSetImpl 类加载到 Map 中缓存,从而绕过 AutoType 的检测
这里有两大版本范围:
- 1.2.25-1.2.32 版本:未开启 AutoTypeSupport 时能成功利用,开启 AutoTypeSupport 不能利用
- 1.2.33-1.2.47 版本:无论是否开启 AutoTypeSupport,都能成功利用
poc:
1.2.48 之后版本,小弟水平有限还未复现研究,payload 需要注意的细节还未探索
Fastjson 1.2.36 - 1.2.62
正则表达式拒绝服务漏洞
Fastjson1.2.5 ⇐ 1.2.59
需要开启 AutoType
Fastjson1.2.5 ⇐ 1.2.60
需开启 autoType:
Fastjson1.2.5 ⇐ 1.2.61
Fastjson <1.2.62
- 需要开启 AutoType;
- Fastjson ⇐ 1.2.62;
- JNDI 注入利用所受的 JDK 版本限制;
- 目标服务端需要存在 xbean-reflect 包;
fastjson⇐1.2.66
前提条件
- 开启 AutoType;
- Fastjson ⇐ 1.2.66;
- JNDI 注入利用所受的 JDK 版本限制;
- org.apache.shiro.jndi.JndiObjectFactory 类需要 shiro-core 包;
- br.com.anteros.dbcp.AnterosDBCPConfig 类需要 Anteros-Core 和 Anteros-DBCP 包;
- com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig 类需要 ibatis-sqlmap 和 jta 包;
适用于 jdk11 以上版本的写文件的 payload:
fastjson⇐1.2.67
前提条件
- 开启 AutoType;
- Fastjson ⇐ 1.2.67;
- JNDI 注入利用所受的 JDK 版本限制;
- org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup 类需要 ignite-core、ignite-jta 和 jta 依赖;
- org.apache.shiro.jndi.JndiObjectFactory 类需要 shiro-core 和 slf4j-api 依赖;
fastjson⇐1.2.68
- Fastjson ⇐ 1.2.68;
- 利用类必须是 expectClass 类的子类或实现类,并且不在黑名单中;
无需开启 AutoType,直接成功绕过 CheckAutoType()的检测从而触发执行:
读文件
写文件
写文件
写文件
适用于 jdk8/10 的
jdk 8 - position 写入的长度,必须和 base64 编码前的长度一致。
写文件,来自@W.K 修改
2021 黑帽大会腾讯玄武披露
详细漏洞原理待研究
https://b1ue.cn/archives/506.html
fastjson⇐1.2.68
fastjson 未知版本
待探索
fastjson < 1.2.83
- 具体版本 1.2.76 ⇐ fastjson < 1.2.83
- 依赖 groovy
具体参考 https://github.com/Lonely-night/fastjsonVul
bypasswaf
绕过 WAF ,在部分中间件中,multipart 支持指定
Content-Transformer-Encoding 可以使用 Base64 或 quoted-printable (QP
编码) 来绕过 WAF
大量字符绕过 WAF
各种特性
文章推荐:https://www.sec-in.com/article/950
Fastjson 默认会去除键、值外的空格、=\b=、=\n=、=\r=、=\f=等,同时还会自动将键与值进行 unicode 与十六进制解码。