本文旨在科普软件安全相关知识,助力企业有效防范软件安全漏洞,提升网络安全防护能力。
final修饰符(关键字),若类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为abstract,又被声明为final。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。被声明为final的方法也同样只能使用,不能重载。方法的参数被final修饰表示在方法体内,该参数的值不可以被修改。
finalize是方法名。Java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在Object类中定义的,因此所有的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。
01 什么是finalize()方法声明为public缺陷?
该程序通过将 finalize() 方法声明为 public 违反了移动代码的安全编码原则。
02 finalize()方法声明为public缺陷构成条件有哪些?
例如:
public void finalize() throws Throwable {
dispose();
super.finalize();
}
常见的JVM会通过GC的垃圾回收线程来进行finalize函数的调用。由于垃圾回收线程比较重要(人家好歹也是JVM的一个组成部分嘛),为了防止finalize函数抛出的异常影响到垃圾回收线程的运作,垃圾回收线程会在调用每一个finalize函数时进行try catch,如果捕获到异常,就直接丢弃,然后接着处理下一个失效对象的finalize函数。
一般finalize会使用protected,因为使用protected只会允许当前类和子类对其进行使用,如果使用public,则相当于把finalize公开,会带来很多不确定性和风险性。
finalize()方法的通用格式如下:
protected void finalize( )
{
// finalization code here
}
03 finalize()方法声明为public缺陷的后果有哪些??
程序永远不应该显式调用finalize,除非在finalize() 的实现中调用super.finalize()。在移动代码情况下,如果攻击者可以恶意调用 finalize() 方法,因为它是公开访问的,否则手动垃圾收集的其他容易出错的做法可能会成为安全威胁。
04 finalize()方法声明为public缺陷样例:
为了有效地检查给定的操作是否被授权,必须使用一些强身份验证和方法保护的手段。通过用户名口令、数字证书等其他手段对用户身份进行鉴别。
package SJT11683.S66;
import lombok.SneakyThrows;
public class SJT6617R {
@SneakyThrows
public void finalize() {
discardNative();
super.finalize();
}
private void discardNative() {
}
}
使用Wukong代码安全检测工具检测上述程序代码,则可以发现代码中存在着“ finalize() Method Declared Public”的安全漏洞。请见下图:
“未检查的错误情况”在CWE中编号为CWE-583: finalize() Method Declared Public