Java 序列化代理上的字节流攻击:安全吗?
职位结构:Java 序列化代理上的字节流攻击:安全吗?,java,security,serialization,Java,Security,Serialization,职位结构: 情景 问题: 代码和输出 其他信息/评论 1。 情景 假设我可以编辑(可序列化类的)SerializedProxy(私有嵌套)的序列化字节流,以破坏SerializedProxy本身的不变量,因此,我可以更改正在反序列化的实例 在这种情况下,我可以访问SerializedProxy类的序列化形式,在不强制readResolve()中的不变量的情况下,对被序列化的类的字节流攻击同样容易 2。问题 SerializationProxy方法(wrt字节流攻击)的安全性是否纯粹基于以下假设:
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产出:
aced 0005 7372 0029 5365 7269 616c 697a
6174 696f 6e50 726f 7879 5465 7374 2453
6572 6961 6c69 7a61 7469 6f6e 5072 6f78
793b 8ab7 89f9 dd6d aa02 0001 4900 0269
6478 7000 00005
3.2更改序列化的SerializedProxy,将变量的值更改为6
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);
}
}
aced 0005 7372 0029 5365 7269 616c 697a
6174 696f 6e50 726f 7879 5465 7374 2453
6572 6961 6c69 7a61 7469 6f6e 5072 6f78
793b 8ab7 89f9 dd6d aa02 0001 4900 0269
6478 7000 00006
3.3通过反序列化来初始化可序列化类修改后的SerializedProxy: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”后产生的好奇心。这里提出的另一个假设是,攻击者可以通过反复试验,在不知道类结构的情况下,对字节流进行有效更改。反序列化时,串行代理必须强制执行与构造函数相同的不变量(或者,如果使用静态创建方法,则强制执行不变量)。这通常是通过串行代理使用公共构造函数(或方法)来创建真实对象来实现的 在问题代码中,
id
始终为5的不变量是静态创建方法(main
)。串行代理代码不使用该选项
注意:您的SerializationProxyTest
是子类化的。Java字节码不要求类具有构造函数,因此基类不需要具有可访问的构造函数。通常,类的任何非最终公共或受保护方法都是可重写的
还要注意的是,第三版有效Java的序列化章节中有一些更正-不要使用早期版本。代理不应该为它正在代理的类保留不变量吗?例如,在我上面的问题中,我希望SerializationProxy建立与SerializationProxyTest实例相同的不变量,该实例在main方法中以id=5创建。请忽略我之前的评论:重新阅读您的答案可以澄清问题。另外,感谢您提供有关上一版本已过时的信息。