Weblogic系列文章,还是绕过黑名单。
复现
https://github.com/5up3rc/weblogic_cmd 修改payload类型

成功执行命令,断点同样下在InvokerTransformer的transform(),堆栈如下。
transform:123, InvokerTransformer (org.apache.commons.collections.functors)
transform:122, ChainedTransformer (org.apache.commons.collections.functors)
get:157, LazyMap (org.apache.commons.collections.map)
invoke:50, AnnotationInvocationHandler (sun.reflect.annotation)
entrySet:-1, $Proxy57
readObject:327, AnnotationInvocationHandler (sun.reflect.annotation)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:39, NativeMethodAccessorImpl (sun.reflect)
invoke:25, DelegatingMethodAccessorImpl (sun.reflect)
invoke:597, Method (java.lang.reflect)
invokeReadObject:974, ObjectStreamClass (java.io)
readSerialData:1848, ObjectInputStream (java.io)
readOrdinaryObject:1752, ObjectInputStream (java.io)
readObject0:1328, ObjectInputStream (java.io)
readObject:350, ObjectInputStream (java.io)
readResolve:58, MarshalledObject (weblogic.corba.utils)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:39, NativeMethodAccessorImpl (sun.reflect)
invoke:25, DelegatingMethodAccessorImpl (sun.reflect)
invoke:597, Method (java.lang.reflect)
invokeReadResolve:1061, ObjectStreamClass (java.io)
readOrdinaryObject:1761, ObjectInputStream (java.io)
readObject0:1328, ObjectInputStream (java.io)
readObject:350, ObjectInputStream (java.io)
readObject:69, InboundMsgAbbrev (weblogic.rjvm)
read:41, InboundMsgAbbrev (weblogic.rjvm)
readMsgAbbrevs:283, MsgAbbrevJVMConnection (weblogic.rjvm)
init:215, MsgAbbrevInputStream (weblogic.rjvm)
dispatch:498, MsgAbbrevJVMConnection (weblogic.rjvm)
dispatch:330, MuxableSocketT3 (weblogic.rjvm.t3)
dispatch:394, BaseAbstractMuxableSocket (weblogic.socket)
readReadySocketOnce:960, SocketMuxer (weblogic.socket)
readReadySocket:897, SocketMuxer (weblogic.socket)
processSockets:130, PosixSocketMuxer (weblogic.socket)
run:29, SocketReaderRequest (weblogic.socket)
execute:42, SocketReaderRequest (weblogic.socket)
execute:145, ExecuteThread (weblogic.kernel)
run:117, ExecuteThread (weblogic.kernel)
用的common-collection1,MarshalledObject 在 (weblogic.corba.utils) 中 WEB-INFlibweblogic.jar!weblogiccorbautilsMarshalledObject.class
分析
同样是绕过黑名单,将反序列化的对象封装进了weblogic.corba.utils.MarshalledObject,然后再对MarshalledObject进行序列化,生成payload字节码。由于MarshalledObject不在WebLogic黑名单里,可正常反序列化,在反序列化时MarshalledObject对象调用readObject时对MarshalledObject封装的序列化对象再次反序列化,可以绕过黑名单的限制。
看下weblogic_cmd中如何构造的

handler是构造的cc对象,进入BypassPayloadSelector.selectBypass()

根据TYPE决定使用什么来构造payload,跟进到marshalledObject(payload)

将构造的cc对象封装进MarshalledObject对象marshalledObject,然后return,进入Serializables.serialize(_handler)

拿到序列化对象的字节码数组,然后通过t3协议发送出去,后面不在解释。
总的来说,就是将cc对象封装进MarshalledObject,MarshalledObject不在黑名单中,那么执行他的readObject()就可以触发cc链。
再来看下weblogic在哪触发的readObject(),断到MarshalledObject.class的48行。

这里的readObject()触发反序列化,怎么进入到readResolve()这个方法的?查看堆栈进入invokeReadResolve()

这里通过反射调用var1也就是MarshalledObject对象的readResolve()方法。var1中包含了我们恶意的序列化数据,它怎么传进来的?
进入堆栈中readOrdinaryObject()
private Object readOrdinaryObject(boolean var1) throws IOException {
if (this.bin.readByte() != 115) {
throw new InternalError();
} else {
ObjectStreamClass var2 = this.readClassDesc(false);
var2.checkDeserialize();
Object var3;
try {
var3 = var2.isInstantiable() ? var2.newInstance() : null;
} catch (Exception var6) {
throw (IOException)(new InvalidClassException(var2.forClass().getName(), "unable to create instance")).initCause(var6);
}
this.passHandle = this.handles.assign(var1 ? unsharedMarker : var3);
ClassNotFoundException var4 = var2.getResolveException();
if (var4 != null) {
this.handles.markException(this.passHandle, var4);
}
if (var2.isExternalizable()) {
this.readExternalData((Externalizable)var3, var2);
} else {
this.readSerialData(var3, var2);
}
this.handles.finish(this.passHandle);
if (var3 != null && this.handles.lookupException(this.passHandle) == null && var2.hasReadResolveMethod()) {
Object var5 = var2.invokeReadResolve(var3);
if (var1 && var5.getClass().isArray()) {
var5 = cloneArray(var5);
}
if (var5 != var3) {
var3 = var5;
this.handles.setObject(this.passHandle, var5);
}
}
return var3;
}
}
在这里调用了invokeReadResolve(),参数var3在上文经过this.readClassDesc().newInstance()拿到传入t3协议的MarshalledObject对象,具体做了什么处理不深入研究。
总结
t3传入MarshalledObject对象 -> readOrdinaryObject() 拿到MarshalledObject对象 -> invokeReadResolve() 反射调用MarshalledObject对象的readResolve() -> readObject()触发cc反序列化。
参考
- jdk最好用1.6的,不然总是定位不到正确的函数。
- https://www.cnblogs.com/afanti/p/10240232.html
文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。
原创文章,作者:Y4er,未经授权禁止转载!如若转载,请联系作者:Y4er