文章详情
从Weblogic原理上探究CVE-2015-4852、CVE-2016-0638、CVE-2016-3510究竟怎么一回事
目前。网上关于CVE-2015-4852漏洞的资料很多,但是针对CVE-2015-4852漏洞如何修复,修复补丁又是如何生效的却少之又少;而CVE-2016-0638、CVE-2016-3510这两个漏洞又是如何绕过CVE-2015-4852补丁的,通常只是在介绍Weblogic系列漏洞时被一句话带过。
CVE-2015-4852、CVE-2016-0638以及CVE-2016-3510,这三个漏洞有着极其相似的地方,其本质就是利用了Weblogic反序列化机制,而官方在修复CVE-2015-4852时,也并未对这个机制进行调整,而仅仅是在此基础上增加了一个关卡:黑名单。
因此,在彻底搞清楚Weblogic反序列化漏洞的原理以及如何修复这个问题之前,很有必要弄清楚Weblogic处理流量中的java反序列化数据的流程。只有清楚了这一点,才能很好的理解如下几个问题:
CVE-2015-4852是如何产生的以及后续是如何修复的?
修复CVE-2015-4852,为何要在resolveClass:108,InboundMsgAbbrev\$ServerChannelInputStream (weblogic.rjvm)处添加黑名单?
CVE-2016-0638、CVE-2016-3510是如何绕过修复?二者的绕过方式有何相同与不同?
Weblogic 反序列化攻击时序
为了搞清楚CVE-2015-4852、CVE-2016-0638、CVE-2016-3510中的种种疑团,我们需要首先来弄明白一些原理性的东西,我们先从Weblogic
反序列化攻击时序入手,看看Weblogic是如何从流量中将序列化字节码进行反序列化。
首先贴出一张Weblogic 反序列化攻击时序图
这张图是从我的好朋友廖新喜大佬博客扒下来的,也欢迎大家去读一读他的关于java漏洞的分析文章:
http://xxlegend.com/2018/06/20/%E5%85%88%E7%9F%A5%E8%AE%AE%E9%A2%98%20Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AE%9E%E6%88%98%20%E8%A7%A3%E8%AF%BB/
上图为一张完整的Weblogic反序列化攻击时序图,庞大而且繁杂,不如我们将其拆分开,首先说说Weblogic如何从流量数据取出序列化数据并获取其类对象的过程。
从流量数据到Class对象
首先我们来看一张图:
Weblogic通过7001端口,获取到流量中T3协议的java反序列化数据。从上图中readObject开始,经过流程中的一步步的加工,并最终于上图流程终点处的resolveProxyClass或resolveClass处将流量中的代理类/类类型的字节流转变为了对应的Class对象。
首先我们可以发现:在ObjectInputStream (java.io)中的readClassDesc方法处,存在着分叉点,导致了序列化流量流向了两个不同的分支:其中一些流量流向了readProxyDesc并最终采用resolveProxyClass获取类对象,而另一些则流向了readNonProxyDesc并最终使用resolveClass获取类对象。
readClassDesc是什么?
从上文来看,流量数据经过readClassDesc并驶入了不同的处理分支。
首先来看一下readClassDesc方法的官方注释:“readClassDesc方法读入并返回(可能为null)类描述符。将passHandle设置为类描述符的已分配句柄。”
如果想理解官方注释的含义,需要扩充一些java序列化的知识:
java序列化数据在流量传输,并不是随随便便杂乱无章的,序列化数据的格式是要遵循序列化流协议。
序列化流协议定义了字节流中传输的对象的基本结构。该协议定义了对象的每个属性:其类,其字段以及写入的数据,以及以后由类特定的方法读取的数据。
字节流中对象的表示可以用一定的语法格式来描述。对于空对象,新对象,类,数组,字符串和对流中已有对象的反向引用,都有特殊的表示形式。比如说在字节流中传递的序列化数据中,字符串有字符串类型的特定格式、对象有对象类型的特定格式、类结构有着类结构。而TC_STRING、TC_OBJECT、TC_CLASSDESC则是他们的描述符,他们标识了接下来这段字节流中的数据是什么类型格式的
以TC_CLASSDESC为例,TC_CLASSDESC在流量中的值是(byte)0x72,在序列化流协议中,当这个值出现后,代表接下来的数据将开始一段Class的描述(DESC=description),即TC_CLASSDESC描述符(byte)0x72后面的字节流数据为Class类型。通过这些描述符,程序可以正确的解析流量中的序列化数据。
如果对这部分感兴趣,可以参照oracle文档:
https://www.oracle.com/security-alerts/cpuoct2020traditional.html
readClassDesc的功能很简单:读入字节流,通过读取字节流中的描述符来确定字节流中传递数据的类型,并交给对应的方法进行处理。
接下来我们看看readClassDesc的实现
private ObjectStreamClass readClassDesc(boolean unshared)
throws IOException
{
byte tc = bin.peekByte();
switch (tc) {
case TC_NULL:
return (ObjectStreamClass) readNull();
case TC_REFERENCE:
return (ObjectStreamClass) readHandle(unshared);
case TC_PROXYCLASSDESC:
return readProxyDesc(unshared);
case TC_CLASSDESC:
return readNonProxyDesc(unshared);
default:
throw new StreamCorruptedException(
String.format("invalid type code: %02X", tc));
}
}
上一文章:从JS敏感信息泄露到GETSHELL
下一文章:实战渗透-基于DWR框架下的漏洞探测
相关推荐
- 11-26装逼新境界!iPhoneX qq空间小尾巴上线
- 11-11LinuxkernelBPF模块的相关漏洞分析
- 05-26.net反序列化之XmlSerializer
- 11-06一次艰难的TP渗透测试
- 11-09xxl-jobapi未授权Hessian2反序列化
- 10-20SEO优化排名,百度优化排名
- 11-13华为路由器漏洞CVE-2017-17215复现分析
- 11-17从0到tfp0第一部分:基础知识
- 10-21Spring反射性文件下载漏洞(CVE-2020-5421)分
- 05-11sql注入攻击的原理(sql注入攻击防范)
- 05-26黑客是如何入侵的?常见的黑客手段 黑客攻击
- 05-02小风原创表白网页源码
- 11-03记一次不存在的ecshop实战渗透
- 05-31巧用smb拿下不出网主机