JavaSec系列 - 4. 反序列化与JNDI注入(2)
本章源码: https://github.com/hey3e/JavaSec-Code/tree/main/javasec4
深入分析CVE-2021-21344。
本章源码: https://github.com/hey3e/JavaSec-Code/tree/main/javasec4
深入分析CVE-2021-21344。
本章源码: https://github.com/hey3e/JavaSec-Code/tree/main/javasec3
上章我们了解到,通过控制lookup
方法的参数,可以实现JNDI注入。从控制到注入,就是一条完整的攻击链。我们来看一个实例。
本章源码: https://github.com/hey3e/JavaSec-Code/tree/main/javasec2
命名与目录系统 (Naming and Directory services),如RMI (Remote Method Invocation)、LDAP (Lightweight Directory Access Protocol) 等,能够以类似字典key-value
的name-object
形式对对象进行存储,使得我们可以通过名称来查询并访问对象。JNDI (Java Naming and Directory Interface) 便是该过程的接口。
结合上一章的知识,我们考虑在系统中存储对象序列化后的字节流,当用户进行查询时,系统返回对应的字节流,用户再进行反序列化获取对象。但在实际场景中,如果对象过大,采用该方式往往会给系统带来一定的负担。
于是,JNDI使用Naming References
的方式进行存储,此时,name-object
中的object
并非对象本身,而是对象的引用Reference
,其中包含对象名及其真正被存放的地址codebase。当用户进行查询时,系统返回Reference
,用户解析后再从codebase获取对象。不过这里说的不太严谨,后面会进行补充。
不过,上述从远程codebase加载对象的方式存在许多安全问题,随着jdk版本的迭代,系统对codebase已逐渐不再信任,JNDI受到越来越多的限制。我们下面看一下各版本下JNDI如何实现。