JNDI注入速查手册:我踩过的坑都在这里了
说真的,每次一提到 JNDI 注入,我脑子里就自动浮现出当年第一次打靶场时那个狼狈样——明明 payload 背得滚瓜烂熟,结果一上手就翻车,报错信息看得我一脸懵,后来折腾久了才发现,这玩意儿其实没那么玄乎,关键是要有一份靠谱的速查手册放在手边,所以今天我就把自己整理的 JNDI注入速查手册 分享出来,全是实战里攒下的经验,希望能帮你少走点弯路哈。

先搞明白 JNDI 到底是个啥
JNDI 全称 Java Naming and Directory Interface,翻译过来就是 Java 命名与目录接口,听起来挺唬人对吧?其实你可以把它想象成一个“通讯录”——程序通过名字去查东西,查到的可能是个数据源、一个远程对象,甚至……一个恶意类,哎,问题就出在这个“甚至”上,当 lookup 的地址可控时,攻击者就能把通讯录里原本该填“张三”的地方,偷偷换成“炸弹”,JNDI 注入就这么发生了,是不是有点后背发凉的感觉?
速查手册第一页:常见触发点
我在手册里列了几个高频入口,你记一下:
- InitialContext.lookup(userInput) —— 最经典的,没有之一
- Spring 的 JndiObjectFactoryBean —— 配置不当直接躺枪
- Tomcat 的 JNDI 资源引用 —— 老版本里坑特别多
- Log4j2 的 ${jndi:ldap://...} —— 这个不用我多说了吧,当年闹得沸沸扬扬的
看到 lookup 后面跟着用户输入,你的警报器就该响了,别犹豫!
速查手册第二页:协议怎么选
这块我吃过亏,得重点说说,LDAP 和 RMI 是最常用的两个协议,区别在于:
| 协议 | 特点 | 适用场景 |
|---|---|---|
| LDAP | 回连快,受 JDK 版本限制相对小 | 首选,尤其高版本 JDK |
| RMI | 经典但高版本 JDK 有反序列化限制 | 低版本环境更稳 |
我个人的习惯是:先试 LDAP,不行再换 RMI,别在一棵树上吊死嘛,另外记得本地起个恶意 LDAP 服务,工具像 JNDIExploit、rogue-jndi 都挺顺手的,手册里我把常用命令都抄下来了,复制粘贴就能跑,爽得很。
速查手册第三页:版本绕过那些事儿
这里必须吐槽一句——JDK 版本真的是绕不过去的坎啊!8u191 之后 LDAP 默认不加载远程 codebase 了,很多人到这一步就卡住,别慌,手册里我记了几条路:
- 找本地 Gadget:利用目标 classpath 里已有的利用链,Tomcat 的 BeanFactory
- LDAP 返回序列化数据:配合反序列化链打
- 换协议:某些场景下 RMI 反而能通
说白了就是八个字:因地制宜,灵活变通,死磕一种姿势,累的是自己。
速查手册第四页:防御侧也得懂
光会打不行,咱还得知道怎么防,不然跟脚本小子有啥区别?手册里我专门留了一页:
- 别把用户输入直接丢给 lookup,做白名单校验
- 升级 JDK,关掉不必要的远程 codebase 加载
- 用 SecurityManager(虽然现在有点过时了,但老系统还是有用)
- 日志里出现
jndi:关键字要警惕
唉,说多了都是泪,多少漏洞本质就是一行没校验的代码啊。
写在最后
这份 JNDI注入速查手册 我反复改了好几版,每次实战遇到新姿势就补进去,技术这东西更新太快了,今天的绕过明天可能就失效,所以手册也得跟着“养”,如果你也在学这块,建议自己也建一份,哪怕就记在备忘录里,关键时刻真能救命,好了,不啰嗦了,我去更新手册里的新 payload 了,咱们下回聊!