Rah*_*hul 3 java garbage-collection memory-management finalizer effective-java
我正在阅读Joshua Bloch 的《Effective Java》。第 8项:避免第 2 章的定型剂和清洁剂定型剂和清洁剂中,他指出:
\n\n\n终结器有一个严重的安全问题:它们使您的类容易受到终结器攻击。终结器攻击背后的想法很简单:如果从构造函数或其序列化\nequivalents\xe2\x80\x94中抛出\n异常,则
\nreadObject和readResolve方法(第12)\xe2\x80\x94\n恶意子类的终结器可以在部分构造的\n对象上运行,而该对象应该有\xe2\x80\x9cd。\xe2\x80\x9d 这个终结器可以记录\n对静态字段中的对象,防止其\n被垃圾收集。一旦记录了格式错误的对象,就可以简单地调用该对象上的任意方法,而这些方法本来就不应该被允许存在。从构造函数抛出\n异常应该足以阻止\n对象的存在;在存在终结器的情况下,情况并非如此。\n此类攻击可能会产生可怕的后果。Final 类不会受到终结器攻击,因为没有人可以编写 Final 类的恶意子类。
首先,我知道自 Java 18 以来终结器已被弃用。尽管如此,我认为了解此决定背后的原因很重要。我对上面摘录的理解如下:
\n其次,我希望我对这个问题的概念理解是正确的。然而,Bloch 尚未在具体的代码示例中演示这个问题。也许是因为他不想让我们搞乱Object.
您能用代码向我演示一下吗?
\n例如,如果我有一个超类:
\n/** Superclass */\npublic class DemoSecurityProblem {\n\n}\nRun Code Online (Sandbox Code Playgroud)\n然后通过继承或组合来子类:
\npublic class MaliciousSubClass extends DemoSecurityProblem {\n DemoSecurityProblem demoSecurityProblem = new DemoSecurityProblem();\n}\nRun Code Online (Sandbox Code Playgroud)\n攻击者如何通过终结机制利用这一点?
\n多谢!
\n你的描述基本上是正确的,但事情过于复杂。不需要在static变量中存储任何内容;一旦finalize()调用该方法,该对象就已经复活,因为调用对象上的方法意味着调用可以访问该对象的代码。
将对象引用存储在变量中是一种将生命周期扩展到方法执行之外的方法finalize(),但这对于攻击来说不是必需的。此外,static攻击者还可以将子类设置为内部类,并将引用存储在仍然可访问的外部对象中,而不是使用变量。
所以下面的程序已经足以说明问题了
\npublic class FinalizerAttackExample {\n public static void main(String[] args) throws InterruptedException {\n try {\n new MaliciousSubclass();\n } catch(SecurityException ex) {\n System.out.println("wouldn\'t get hands on a ResourceClass instance");\n }\n System.gc();\n Thread.sleep(2000);\n }\n\n static class ResourceClass {\n ResourceClass() {\n if(!checkCaller()) throw new SecurityException();\n }\n public void criticalAction() {\n System.out.println("ResourceClass.criticalAction()");\n }\n }\n\n /** For our demonstration, all callers are invalid */\n static boolean checkCaller() {\n return false;\n }\n\n static class MaliciousSubclass extends ResourceClass {\n @Override\n protected void finalize() {\n System.out.println("see, I got hands on " + this);\n criticalAction();\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n虽然垃圾收集是不确定的,并且通常不能保证终结器的执行,但此示例将打印
\nwouldn\'t get hands on a ResourceClass instance\nsee, I got hands on FinalizerAttackExample$MaliciousSubclass@7ad74083\nResourceClass.criticalAction()\nRun Code Online (Sandbox Code Playgroud)\n在很多实现上,证明criticalAction()可以在一个不应存在的对象上调用它,因为构造函数抛出了异常。
| 归档时间: |
|
| 查看次数: |
729 次 |
| 最近记录: |