java - 对 SerializationProxy 的字节流攻击:它更安全吗?
问题描述
岗位结构:
- 设想
- 问题
- 代码和输出
- 附加信息/评论
1. 场景 鉴于我可以编辑(私有嵌套)SerializedProxy(属于 Serializable 类)的序列化字节流以打破 SerializedProxy 本身的不变量,因此我可以更改正在反序列化的实例。
在我可以访问 SerializedProxy 类的序列化形式的这种情况下,对正在序列化的类的字节流攻击同样容易,而无需在 readResolve() 中强制执行不变量。
2. 问题
SerializationProxy 方法的所谓安全性——wrt 字节流攻击——是否纯粹基于序列化形式的内容或 SerializedProxy 的源代码总是对攻击者不可用的假设?如果没有,我是否误解或错过了这里的某些实施部分?
3.Code (注意:Serializer是一个将序列化对象写入文件的util类。)
3.1使用值 5 序列化代理。
import java.io.Serializable;
import java.io.InvalidObjectException;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializationProxyTest implements Serializable
{
final int id;
private SerializationProxyTest(int val)
{
id = val;
}
private void writeObject() throws InvalidObjectException, IOException
{
throw new InvalidObjectException("Invalid object called for Serialization: proxy not found.");
}
private Object writeReplace()
{
System.out.println("writeReplace 1 ");
return new SerializationProxy(this);
}
private static class SerializationProxy implements Serializable
{
final int id;
SerializationProxy(SerializationProxyTest obj)
{
this.id = obj.id;
}
/* private void writeObject(ObjectOutputStream oos) throws IOException
{
oos.defaultWriteObject();
} */
private Object readResolve()
{
System.out.println("readResolve step 1 ");
return new SerializationProxyTest(this.id);
// return "Something Else!";
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException
{
Serializer.serializeObject(new SerializationProxyTest(5));
SerializationProxyTest spt = (SerializationProxyTest) Serializer.deserializeObject("/home/code/java/serialized_proxy_class.ser");
System.out.println("stored variable is: " + spt.id);
}
}
3.1 输出:
[java]$ java SerializationProxyTest writeReplace 1 readResolve 1 object is: SerializationProxyTest@4eec7777 stored variable is: 5
ACED 0005 7372 0029 5365 7269 616C 697A 6174 6174 696F 6E50 726F 7879 5465 7374 24574 24572 6572 6961 6C691 6C69 7A69 7A61 7A61 7469 6F6E
3.2更改序列化的 SerializedProxy 以将变量的值更改为 6。
ACED 0005 7372 0029 5365 7269 616C 697A 6174 6174 696F 6E50 726F 7879 5465 7374 24574 24572 6961 6C691 6C69 7A69 7A61 7A61 7469 6F6E
3.3通过反序列化改变后的 SerializedProxy 来初始化 Serializable 类:SerializationProxyTest 类初始化为 6 而不是 5。
SerializationProxyTest spt = (SerializationProxyTest) Serializer.deserializeObject("/home/code/java/serialized_proxy_class.ser");
System.out.println("stored variable is: " + spt.id);
[java]$ java SerializationProxyTest
writeReplace 1
readResolve 1
object is: SerializationProxyTest@4eec7777
stored variable is: 6
4.附加信息/评论:SerializedProxy 方法的某些固有“安全性”的假设只是阅读“有效 Java”时产生的好奇心。这里所做的另一个假设是,即使不知道类结构,攻击者也可以通过反复试验对字节流进行有效更改。
解决方案
反序列化时,串行代理必须强制执行与构造函数相同的不变量(或者,如果您采用该路线,则为静态创建方法)。这通常是通过串行代理使用公共构造函数(或方法)来创建真实对象来实现的。
在问题的代码中,始终为 5 的不变量id
位于静态创建方法 ( main
) 中。串行代理代码不使用它。
注意:你SerializationProxyTest
是可子类化的。Java 字节码不需要类具有构造函数,因此基类没有必要具有可访问的构造函数。通常,您的类的任何非最终公共或受保护方法都可能是可重写的。
另请注意,第 3 版 Effective Java 的序列化章节中有更正 - 不要使用早期版本。
推荐阅读
- python - 如何递归地编写嵌套的 for 循环?
- sql-loader - sqlldr 生成 ORA-00984: column not allowed here - 在尝试添加常量文本时
- sas - 宏不保留在 DATA STEP 的 IF-THEN 循环中
- mongodb - Mongo Aggregation 用默认数组替换数组内的空/空数组字段
- python - 离线更新python库
- xamarin.forms - Xamarin 表单获取列表项计数,其中属性选择为 true
- python - 提取文本然后保存到纯文本文件 - TypeError:需要一个整数(获取类型 str)
- php - Paypal 发送发货国家(使用不同的值 lc 和国家字段)
- php - 复制 .env 文件后无法生成 php artisan 密钥
- angular - 不能连续两次将相同的文件添加到数组中(文件上传表单)