Files
Sec-Interview/Chapter23/23-24.md
T
2025-09-25 04:02:19 +08:00

35 lines
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
### JNDI 如何做 Hook
**1. 使用 Java Agent 动态修改字节码**
这是最强大和最通用的 Hook 方法。Java Agent 可以在不修改源代码的情况下,在 JVM 运行时动态地修改类的字节码
- **原理**:创建一个 Java Agent,并在 JVM 启动时通过 `-javaagent` 参数加载它。在 Agent 的 `premain``agentmain` 方法中,你可以使用 **ASM**、**Javassist** 或 **Byte Buddy** 等字节码操作库,找到 `InitialContext.lookup(name)` 所在的类和方法
- **Hook 实现**:找到目标方法后,可以修改它的字节码,在其原始逻辑执行前或执行后插入你自己的代码
- **插入安全检查**:在 `lookup` 方法的开头,插入一段代码来检查传入的 URL。你可以判断 URL 是否符合预设的白名单,或者直接拒绝所有远程 JNDI 请求
- **记录日志**:将 `lookup` 方法的参数和调用堆栈记录下来,以便进行审计
- **修改返回对象**:如果 URL 被判定为恶意,你可以修改 `lookup` 方法的返回值为一个安全的对象,而不是让其继续进行远程查找
- **优点**:非常灵活,可以 Hook 任何类的任何方法,无需访问源代码
- **缺点**:需要深入理解 Java 字节码,且实现起来比较复杂。
**2. 使用动态代理**
动态代理是一种更高级的 Hook 方法,它通过 Java 的反射机制来创建接口的代理对象
- **原理**:如果你知道应用程序使用的是某个 JNDI 接口(例如 `Context`),你可以创建一个代理对象,这个代理对象会实现相同的接口,并在所有方法调用时,将调用转发给你自己的处理逻辑
- **Hook 实现**
1. 找到应用程序创建 `InitialContext` 的地方
2. 用你自己的代理类替换 `InitialContext` 的实例
3. 在代理类中,拦截 `lookup(name)` 方法的调用
4.`lookup` 方法的实现中,你可以先执行安全检查,然后再决定是否调用原始的 `InitialContext.lookup(name)`
- **优点**:不需要字节码操作,相对简单
- **缺点**:只能 Hook 接口,对于没有实现接口的类不起作用。此外,需要修改应用程序的某些部分来插入代理,不像 Java Agent 那样完全透明
**3. 修改 JVM 参数**
这是最简单的 Hook 方法,但功能也最有限
- **原理**:一些 JVM 实现了特殊的参数来控制 JNDI 的行为。例如,在一些版本的 Java 中,可以通过设置 `com.sun.jndi.rmi.object.trustURLCodebase=false` 来阻止 RMI 客户端加载远程对象
- **Hook 实现**:只需在 JVM 启动命令中添加这些参数即可
- **优点**:非常简单,无需编写代码
- **缺点**:依赖于特定的 JVM 版本和参数,无法进行细粒度的控制,也不能用于日志记录等目的