如何判断反序列化哪个过程出错了?
2022-8-8 16:17:19 Author: 珂技知识分享(查看原文) 阅读量:60 收藏

在实战过程中,很多人只会使用工具,对反序列化的过程不太了解,因此依葫芦画瓢时如果失败了,一下子就不知道到底哪里出了问题。这篇文章就是解决这类问题的。

首先我们得明白反序列化的整个过程,我认为可以分为三个步骤。

1,反序列化入口(jndi,shiro,T3等)。

2,反序列化链(cb链,cc链,JDK7u21等)。

3,反序列化结果(Runtime,jndi,SSRF)。

当然,实际情况可能不是单线程的,比如我最新的文章《从CommonsBeanutils说开去》中,就是jndi——反序列化——cb链——jdbc——任意文件读取这么一个比较复杂的过程。

很多时候我们听说xx有反序列化漏洞,其实不一定指的是完整的反序列化过程,而是1或者2。

比如shiro,本质上是个硬编码key的漏洞,但提供了反序列化入口。

比如fastjson,只有1.2.24/1.2.48/1.2.68这三个版本更新才是因为简便的反序列化入口,其他版本更新都是反序列化链。当然,更确切的反序列化入口是parseObject()等方法。

比如weblogic,CVE-2017-3506/CVE-2017-10271/CVE-2018-3252/CVE-2019-2725/CVE-2019-2729这些XMLDecoder的漏洞都是反序列化入口。之后出现的所有跟反序列化相关的漏洞都仅仅是反序列化链。

从反序列化链的名字也看得出来,既然是链,肯定也由多个链条组成的。所以可能存在多个jar包依赖,而且往往限定了jar包的版本范围。同时这些jar包可能还存在二次依赖,且不同版本可能还有不同的serialVersionUID。具体这里不展开讲,总而言之在反序列化链这个步骤中出问题的可能性最大。

其他方面就不出问题了吗?当然不是,反序列化入口也可能面临waf的拦截,但这种比较直观。而反序列化结果就不一样了,比如我就遇见过至少两次无法使用Runtime,就算能够使用,可能还会面临hids/rasp的防护,想通过SSRF/DNS传递信息,也可能完全不通,jndi也跟JDK版本相关。

以shiro举例,首先我们要判断反序列化入口,也就是经典的rememberMe。

同时还需要爆破key,在爆破key的时候就已经涉及反序列链了,这里用的是shiro自带的SimplePrincipalCollection类取消rememberMe。

然后接下来就是寻找shiro的反序列化链,在P牛的文章中说的很清楚,shiro一定存在P牛版无CC依赖的CB2链。

https://www.leavesongs.com/PENETRATION/commons-beanutils-without-commons-collections.html

但为什么有时候就打不通呢?这种情况推荐先用urldns链和JRMP链来分别探测目标出dns和tcp。urldns链和JRMP链危害较小,payload极短,大多数JDK都支持,一般也不会有人用从底层比如JEP290去限制,反序列化时非常适合拿来探测。注意,目标环境可能存在dnslog黑名单,最好使用冷门或者私人dnslog平台。

其中urldns更是可以用类名来探测依赖,参考我写的项目。

https://github.com/kezibei/Urldns

在shiro反序列化的过程中,我们常碰到如下问题。

1,serialVesionUID

commons-beanutils常见版本为1.8.x和1.9.x,两者的serialVesionUID是不一样的,这导致反序列化的payload不通用。而有漏洞的shiro依赖的版本通常是1.8.x,也不排除其为1.9.x的可能。我的URLDNS项目可以探测出这种小版本的差别。

2,header过长导致tomcat报错

shiro常见问题,但如果你用工具打的一般已经规避了这个问题。

3,重写resolveClass导致部分链失效

如果你用urldns探测出了类,但工具上的链又不行,很可能是因为shiro的特性,原理比较复杂,总而言之需要一种shiro的特殊cb链。这篇文章有很详细的记载。

https://www.anquanke.com/post/id/249604

除此之外,如果目标通外网,也就是打的通JRMP链,可以利用JRMP链进行二次反序列化,就不受shiro重写resolveClass的影响。这种技巧同样应用在weblogic早期反序列化绕过上。

如果确认了cb链可以打的通,还可能会碰上如下问题。

1,反弹shell不通外网

这个时候就要利用ping,curl等命令去探测dnslog,一般来说,极少有目标不通dnslog。如果能执行ping,但反弹不行,那就是常见的不通tcp,只通dns。你需要直接打内存马或者dns马。

2,禁止Runtime

有时候你连ping也不行执行,这个时候很有可能对方禁止了Runtime,你需要用ProcessBuilder/ProcessImpl/NativeLibLoader。

如果对方彻底封杀了命令执行的各种方式,你可以用URL.getContent()来执行一个无危害的SSRF来确认cb链的存在。

当然,更好的方式是直接打内存马。

这是shiro的情况,对于另一个比较常见的fastjson反序列化,我们要优先判断版本。这篇文章总结了判断版本的办法。

https://blog.csdn.net/m0_71692682/article/details/125814861

其核心在于判断fastjson在1.2.24/1.2.48/1.2.68这4个区间中的哪个。

如果大于1.2.68,直接放弃,虽然一直到1.2.80还在报漏洞,但实际已经几乎不可能实现。

在不执行命令的情况下。

<1.2.48可以依靠jndi或者JEditorPane.setPage()来判断是否出网。

1.2.48-1.2.68可以依靠jndi链或者mysql链或者io链来判断是否出网。

如果不出网,fastjson的利用方法将大大降低,而且非常依赖外部链。

<1.2.48存在C3P0的二次反序列化和becl可以不出网直接打内存马。

1.2.48-1.2.68可以靠io链或者JDK11链来读写文件。

这些链都已经公开出来,我的文章《fastjson payload大集合》中提到过绝大部分。

其他常见反序列化项目的情况。

XMLDecoder反序列化的攻防,都集中在weblogic上。其他项目中碰到都是默认无防护的情况,payload非常容易构造,这里不赘述。

XStream只跟版本相关,在官网上公开了所有payload,

http://x-stream.github.io/security.html

weblogic T3/IIOP反序列化在近年,也只跟版本挂钩了,而且反序列化结果已经很难直接执行命令,只能jndi,但通常使用新版本weblogic的也会使用新版本jdk,无法jndi注入,因此新链变得越来越鸡肋。

而且自从采用JEP290之后,也无法通过二次反序列化进行逃逸。以及默认组件都被挖光了,2021年以来的漏洞大部分都集中在coherence上,也就是说不含coherence的weblogic 10反而没有T3/IIOP新链的威胁。当然,现在还在用weblogic 10的站往往一个JDK7u21就打穿了。

所以造就这样一个局面,开T3的weblogic站往往用2020年往前的链就能打穿,而存在2021-2022年新链的weblogic站,往往不开T3。就算开了JDK版本也很高,无法jndi注入。

PS:coherence也有serialVesionUID。

我能找到最新的命令执行的公开payload是CVE-2021-2135。

最新的jndi的公开payload是CVE-2022-21350。

jackson虽然爆出很多反序列化漏洞,但全是反序列化链(水),其从未爆出易于利用的反序列化入口,因此实战中不可能遇到。


文章来源: http://mp.weixin.qq.com/s?__biz=MzUzNDMyNjI3Mg==&mid=2247485456&idx=1&sn=9b9bd796ddb3bea22f229987388426ac&chksm=fa97357fcde0bc698021b3508c8d36c56febf8c23f04ac5b6ec9073ef0be1d25c7734156d886#rd
如有侵权请联系:admin#unsafe.sh