FindBugs引发了一个名为EI_EXPOSE_REP的错误,其中包含以下描述:
EI:可以通过返回对可变对象的引用来公开内部表示
返回对存储在其中一个对象字段中的可变对象值的引用会公开该对象的内部表示。如果不受信任的代码访问实例,并且对可变对象的未经检查的更改会危及安全性或其他重要属性,则需要执行不同的操作。在许多情况下,返回对象的新副本是更好的方法。
关于SO的几个问题(1,2和3)已经解决了如何避免此类错误,我理解这是防止不可变对象修改的开发最佳实践但是我不清楚为什么这样的bug属于MALICIOUS_CODE类别。
这背后的真正威胁是什么?
如果是恶意代码问题,攻击者几乎可以做任何他想做的事情,而且可变性不是最大的问题。如果它是一个漏洞,只有在执行不受信任的代码时才能被利用,而且我看不到任何用例,这是真的。
对此有何看法?
谢谢!
答案 0 :(得分:2)
重点是,无论何时打开实施,您都会有意或无意地运行代码的风险。例如,显然恶意库用户可以反汇编你的jar并以这种方式学习细节 - 关键是最大限度地降低暴露的风险:它无法消除。
访问您的库的外部代码的一个简单示例:
考虑一些简单的东西,比如一个拥有访问级别的对象。如果它是可变的,可以想象图书馆用户可以设置自己的访问级别。任何合理的图书馆都很少会暴露这些微不足道的东西,但这是一个明确的例子,说明内部代表何时可能被滥用。
底线是暴露的可变状态使得代码难以推理,并且难以保护。您的代码或其他人可能会意外或故意修改您自己的代码/库使用的内容。如果您的库在不考虑这一点的情况下改变其行为,您可能会引入一个微妙(或不那么微妙)的错误。
答案 1 :(得分:1)
使对象隐藏状态并提供强大的静态接口的能力是Java移动代码安全的核心。程序员搞这个问题有很多方法可以导致漏洞。
对于值对象,请考虑String
。我们相信任何String
的实例都不会改变。我们不想验证[检查]特定文件名,例如,我们不希望它在实际使用时更改(注意,java.io.File
在这种意义上不起作用)。此外,可变内部可能具有恶意equals
方法(比如说),由封闭类'equals
调用,但恶意获取对其他封闭类实例的内部对象的引用。
引用类型通常是对象功能。通常,它们会削弱它们赋予的对象的能力(通过构造函数)。比如说,您只能通过您有权访问的实例将文件写入特定目录,但它有一个能够写入整个文件系统的字段。
然后是Java 2安全模型,这绝不是一件好事。内部对象可能具有在特权上下文中调用的方法,这通常不是问题。现在,恶意方放置在对象(可信类型)中,该对象执行在该上下文中不应该执行的操作。
当然,要注意随机的子类化。他们可能会在将来的版本中获得get
方法。
话虽如此,在我看来,来自Findbugs的这个警告没有帮助。代码可能不是为了隐藏对象。
(有关暴露内部物体问题的详细描述,请参阅Michael Feathers Working Effectively with Legacy Code的第13章(和第14章)。)