警告
本文最后更新于 2020-02-12 ,文中内容可能已过时。
Weblogic系列文章,还是绕过黑名单。
https://github.com/5up3rc/weblogic_cmd 修改payload类型
成功执行命令,断点同样下在InvokerTransformer的transform(),堆栈如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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-INF\lib\weblogic.jar!\weblogic\corba\utils\MarshalledObject.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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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 文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。