在java.lang.SecurityManager
中,有一个布尔值字段,称为Initialized。
public class SecurityManager {
/*
* Have we been initialized. Effective against finalizer attacks.
*/
private boolean initialized = false;
//some code
/**
* Constructs a new <code>SecurityManager</code>.
*
* <p> If there is a security manager already installed, this method first
* calls the security manager's <code>checkPermission</code> method
* with the <code>RuntimePermission("createSecurityManager")</code>
* permission to ensure the calling thread has permission to create a new
* security manager.
* This may result in throwing a <code>SecurityException</code>.
*
* @exception java.lang.SecurityException if a security manager already
* exists and its <code>checkPermission</code> method
* doesn't allow creation of a new security manager.
* @see java.lang.System#getSecurityManager()
* @see #checkPermission(java.security.Permission) checkPermission
* @see java.lang.RuntimePermission
*/
public SecurityManager() {
synchronized(SecurityManager.class) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// ask the currently installed security manager if we
// can create a new one.
sm.checkPermission(new RuntimePermission
("createSecurityManager"));
}
initialized = true;
}
}
//some code
}
因此,显然,默认情况下,初始化字段将为false
,但是如果实例化通过安全检查并成功,则初始化字段将被分配为true
。初始化字段上方只有一条评论,说它对终结器攻击有效,并且未提供有关该字段的更多描述。
我在互联网上搜索了finalizer attacks。据我了解,我们不应该依赖不受信任的代码可以覆盖的方法。但是它与初始化字段有何关系?我仍然可以继承java.lang.SecurityManager
,并且如果安装了SecurityManager但允许通过反射访问私有字段,则应该可以编辑初始化的字段。那么对终结器攻击如何有效?
答案 0 :(得分:1)
这是一种较旧的保护技术: https://www.ibm.com/developerworks/java/library/j-fv/j-fv-pdf.pdf
简而言之,终结器攻击是当您重写对象的finalize()
方法时,该方法用作GC调用以释放本地资源的析构函数。但是,一旦您继承了子类或对其进行了重写,则原始代码的不变式/“承诺”将不再成立。
如何避免攻击
直到Java语言规范(JLS)的第三版发布 Java SE 6中实施的唯一避免攻击的方法-使用
initialized
标志,禁止子类化或创建final
终结器-令人满意的解决方案。使用初始化标志:
避免攻击的一种方法是使用
initialized
标志,即 正确创建对象后,将其设置为true。每种方法 该类首先检查是否设置了initialized
并抛出一个 如果不是,则为例外。这种编码写起来很累,是 容易被意外遗漏,并且不会阻止攻击者 该方法的子类。