43 lines
3.5 KiB
Markdown
43 lines
3.5 KiB
Markdown
### 反序列化除了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()` 方法,从而触发攻击链 |