FindBugs:EI_EXPOSE_REP背后的真正威胁

FindBugs引发了一个名为EI_EXPOSE_REP的错误,其描述如下:

EI:可以通过返回对可变对象的引用来公开内部表示

返回对存储在对象的一个​​字段中的可变对象值的引用会公开对象的内部表示。 如果不受信任的代码访问实例,并且对可变对象的未经检查的更改会危及安全性或其他重要属性,则需要执行不同的操作。 在许多情况下,返回对象的新副本是更好的方法。

关于SO( 1,2和3 )的几个问题已经解决了如何避免这种错误,我理解这是防止不可变对象修改的开发最佳实践,但是我不清楚为什么这样的bug属于MALICIOUS_CODE类别。

这背后的真正威胁是什么?

如果这是一个恶意代码问题,攻击者几乎可以做任何他想做的事情,可变性不会是最大的问题。 如果它是一个漏洞,只有在执行了不受信任的代码时它才能被利用,而我无法看到任何这样的用例。

对此有何看法?

谢谢 !

关键在于,无论何时打开实现,您都会冒着代码造成损害的风险 ,无论是有意还是无意。 例如,显然恶意库用户可以反汇编你的jar子并以这种方式学习细节 – 关键是要尽量减少暴露的风险:它无法消除。

访问您的库的外部代码的一个简单示例:

考虑一些简单的东西,比如一个拥有访问级别的对象。 如果它是可变的,可以想象图书馆用户可以设置自己的访问级别。 任何合理的图书馆都很少会暴露这些微不足道的东西,但这是一个很明显的例子,说明内部表示何时可能被滥用。

底线是暴露的可变状态使得代码难以推理,并且难以保护。 您的代码或其他人可能会意外或故意修改您自己的代码/库使用的内容。 如果您的库在不考虑这一点的情况下更改其行为,您可能会引入一个微妙(或不那么微妙)的错误。

使对象隐藏状态并提供强大的静态接口的能力是Java移动代码安全的核心。 程序员搞这个问题有很多方法可以导致漏洞。

对于值对象,请考虑String 。 我们相信String任何实例都不会改变。 我们不想validation[检查]特定的文件名,例如,当我们实际使用它时我们不希望它改变(注意, java.io.File在这个意义上不能很好地工作)。 同样,可变内部可能有恶意equals方法(比如说),由封闭类’ equals调用,但恶意获取对其他封闭类实例的内部对象的引用。

引用类型通常是对象function 。 通常,它们会削弱它们赋予的对象的能力(通过构造函数)。 比如说,您只能通过您有权访问的实例将文件写入特定目录,但它有一个能够写入整个文件系统的字段。

然后是Java 2安全模型,这绝不是一件好事。 内部对象可能具有在特权上下文中调用的方法,这通常不是问题。 现在,恶意方放置在对象(可信类型)中,该对象执行在该上下文中不应该执行的操作。

当然,要注意随机的子类化。 他们可能会在将来的版本中获得get方法。

话虽如此,在我看来,来自Findbugs的这个警告没有帮助。 代码可能不是为了隐藏对象。

(有关暴露内部对象问题的详细描述,请参阅Michael Feathers 有效使用遗留代码的第13章(和第14章)。)