java - 为什么使用克隆进行防御性复制会带来安全问题?

标签 java security defensive-programming

最近我正在阅读 Joshua Bloch 的第二版 Effective Java。在第 39 项中,他提到制作作为参数传递的可变对象的防御副本是个好主意,比如在给定类 Foo 的构造函数中,如果这些对象稍后用于表示类 Foo 的状态。在同一上下文中,他提到要避免使用非最终类的 clone() 方法,因为它可能会返回旨在执行恶意操作的不受信任子类的实例。

这是我不太清楚的。作为恶意子类的示例,他提到了一个类,该类可以“在创建时在私有(private)静态列表中记录对每个实例的引用,并允许攻击者访问该列表”。

我的疑问:

  1. 他的意思是这个恶意类实际上可以记录封装类的所有private/protected/package/public实例的引用吗?

  2. 如果是这样,那怎么可能呢?你能给我举个例子吗?

谢谢!

最佳答案

作为典型的安全措施,列出适用的上下文非常重要。我们对潜在恶意代码可以访问受攻击的受信任类的情况感兴趣。例如,在浏览器中,不受信任的代码可以访问 Java PlugIn 受信任的库。以前是 RMI 加载远程代码的情况,但现在已经符合默认安全的策略。

可变参数的问题在于它们可以在检查有效性和使用之间更改。这被称为检查时间/使用时间漏洞,TOCTOU(或 TOC2TOU)。实际上,这可以是两种用途,而不是一种专门用于检查的用途。其他设计糟糕的类看起来不可变但可以子类化(例如 java.io.File),可以被子类化为可变类,作为它们在调用时执行任意代码的能力的一部分。

这里讨论的特定攻击场景是覆盖 clone 以阻止复制尝试。在这种情况下,对 static 的引用是无关紧要的(它在 finalizer 攻击中很重要,但主要反射(reflect)了攻击代码很少被设计成干净的)。

class MaliciousDate {
    private final List<MaliciousDate> dates;
    public MaliciousDate(List<MaliciousDate> dates) {
        this.dates = dates;
    }
    @Override public MaliciousDate clone() {
        MalicousDate other = (MalicousDate)super.clone(); // Or new MalicousDate
        synchronized (dates) {
            dates.add(other);
        }
        return other; // Or return this;
    }
}

修改书上的例子。

public Period(Date start, Date end) {
    // Failing defensive copy.
    start = (Date)start.clone();
    end   = (Date)end  .clone();

    if (start.compareTo(end) > 0)
        throw new IllegalArgumentExcpetion();
    this.start = start;
    this.end = end;
} 

然后攻击:

List<MaliciousDate> dates = new ArrayList<>()
Date start = new MaliciousDate(dates);
Date end = new MaliciousDate(dates);
Period p = new Period(start, end);
dates.get(1).setYear(78); // Modifies internals of p!

结论:使您的值类型稳健不可变。更多信息在非常棒的Secure Coding Guidelines for the Java Programming Language .

关于java - 为什么使用克隆进行防御性复制会带来安全问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21897622/

相关文章:

java - 如果源代码是隐藏的,为什么还需要防御性编程?

security - 网站编程漏洞 list

java - jpa - 两个不同的 @Embeddable 类中的多个 @ElementCollection

asp.net - 如何防止其他用户下载/打开其他文件?

security - 如何处理 docker 容器中的安全更新?

security - 同源策略容易规避?

java - 如何在 Java 中使用 themoviedb.org api

java - 延迟加载奇怪的行为

java - Google App Engine - Memcache - Python 的 client.add 的 Java 版本?

c# - 自动空值检查