1

正如安全编码网站所解释的:

Blockquote 这个不兼容的代码示例显示了一个带有私有构造函数的类 Ser,表明该类外部的代码应该无法创建它的实例。该类实现 java.io.Serializable 并定义公共 readObject() 和 writeObject() 方法。因此,不受信任的代码可以使用 readObject() 获取重构的对象,并可以使用 writeObject() 写入流。

public class Ser implements Serializable {
  private final long serialVersionUID = 123456789;
  private Ser() {
    // initialize
  }
  public static void writeObject(final ObjectOutputStream stream)
    throws IOException {
    stream.defaultWriteObject();
  }
  public static void readObject(final ObjectInputStream stream)
      throws IOException, ClassNotFoundException {
    stream.defaultReadObject();
  }
}

如您所知,writeObject 和 readObject 方法应该被定义为私有(并且也没有 static 关键字!)并且这些方法不被 JVM 调用。

我的问题是:为什么这些方法不安全。这些方法甚至不被 JVM 调用!!我想要一个示例代码,向我展示此代码可能不安全,并且攻击者可以访问我们的数据。

任何帮助将不胜感激。

4

2 回答 2

1

这里显示的代码肯定有一个错误,但它并不是真正的安全漏洞,它只是一个编程错误。不幸的是,安全编码网站在一些关于如何修复它的声明中是不正确的。请参阅该文章下方的评论;他们讨论了一些错误。

首先,正如您所指出的,由于声明了这些方法static,因此序列化机制根本不会调用它们。(序列化主要是基于库的,而不是基于 JVM 的。)错误是,如果您想使用这些方法自定义序列化格式,它根本行不通。无论您在这些方法中添加什么,都将使用默认的序列化格式。

(这也有点奇怪,自定义readObjectwriteObject方法只调用默认的读/写例程,根本不提供自定义,但这可能是为了举例。)

这段代码不安全吗?不,不是。它只是不会按预期的方式工作。

用户 Powerlord 询问攻击者是否不能只调用Ser.readObject(myInputStream). 那是行不通的,因为该defaultReadObject方法只允许在对象的反序列化期间被调用。如果不是,它会抛出NotActiveException.

此代码的修复是更改方法,以便它们是private实例方法而不是public static方法。这将导致序列化机制调用这些方法,以便它们可以实现一些格式自定义。

但是,当引用的文章指出这将阻止攻击者创建不需要的实例时,它是不正确的。反序列化会绕过私有构造函数是正确的。但是 makereadObjectwriteObjectprivate不会阻止攻击者反序列化尽可能多的此类实例。这大概就是霸王所关心的吧。我可以轻松地编造我自己的字节流并从中反序列化对象,只要我愿意,我可以使用我选择的任何内容:

ObjectInputStream ois = new ObjectInputStream(myInputStream);
Ser anotherSerInstance = (Ser)ois.readObject();

为了防止这种情况,Ser该类必须实现一些签入readObject并抛出类似的东西,InvalidObjectException如果它想防止反序列化。另一种方法是让它实现readResolve并返回一个已经创建的实例(例如单例),而不是创建一个新实例。

有关进一步的讨论,请参阅 Bloch,Effective Java,第 74-78 条。请注意,如果您想要单例,它建议使用 anenum而不是。readResolve

于 2014-08-22T07:38:49.997 回答
0

网站不正确。对象序列化规范writeObject()明确指出

private void writeObject(ObjectOutputStream stream)
    throws IOException;

同样的签名readObject()

private void readObject(ObjectInputStream stream)
    throws IOException, ClassNotFoundException;

如果您制作它们public ,否则 static它们将不会被调用。在这里,他们都是。

于 2014-08-22T07:50:59.057 回答