对象反射的安全风险是啥?
Posted
技术标签:
【中文标题】对象反射的安全风险是啥?【英文标题】:What is the security risk of object reflection?对象反射的安全风险是什么? 【发布时间】:2011-03-01 11:33:38 【问题描述】:因此,经过几个小时的解决方法,目前在 Google App Engine 上禁用了反射的限制,我想知道是否有人可以帮助我理解为什么对象反射可能是一种威胁。是因为我可以检查一个类的私有变量还是有其他更深层次的原因?
【问题讨论】:
查看this question。 是被禁用了,还是有安全管理器? 这篇文章是关于.net的。 .net 和 java 是否可比 w.r.t.反射和安全? 我不认为这是一个答案。 +1 杀手级问题。不要关闭它,我对答案不满意。 【参考方案1】:1 - 反射(作为一个概念)确实与安全/安保正交。
Java 的设计非常重视使其成为安全平台,具有 静态类型、安全管理器、类加载器,并且没有办法拧指针/内存。你可以在Masterminds of programming 阅读 James Gosling 的采访,这很有趣。
但是,您拥有的 反射 能力越强,就越难以确保事情的安全。反射会明显击败静态类型,并可能导致运行时错误。
但更微妙的事情也可能发生。例如,类加载器——可以被认为是系统中的 reflective 钩子——在 Java 的早期版本中没有正确设计,从而导致潜在的类型替换。 Gilad Bracha 的文章Dynamic class loading in the JVM, 对这些问题很有见地。
反射不能完全关闭;总是可以反思自己的公共领域/方法。但是,可以禁用使用 AccessibleObject.setAccessible
对私有结构的反射,因为它破坏了封装。通过访问私有字段等,可以检查和修改内部数据。它可能导致各种恶意攻击,例如
strings
不再是不可变的,可以更改(参见question)
您可以透露不属于您的对象的敏感信息
...其他漏洞利用...
最后还有其他将安全置于危险境地的机制,尤其是sun.misc.Unsafe
,它可以直接访问内存——指针又回来了。
2 - 现在,问题是反思(在实践中)是否会导致这么多风险。
我已经阅读了@dbyrne 指向的链接,但它主要是关于.net 的。此外,我不确切知道 Google App 禁用了什么。是只有ReflectPermission
,还是安全管理员的其他权限?一种危险显然是访问文件系统并搞乱。
在实践中可以争论访问私有数据和破坏封装的问题。编写安全代码确实非常困难,即使不更改访问修饰符,您也可以以不适当的方式对类进行子类化——除非它们是final
,或者甚至更好,密封——并传递它们。例如,defensive copying 试图防止这种情况发生。
由于向下转换,类型安全无论如何也受到运行时错误的威胁,所以这一点也可以争论。
在共享/托管环境中,安全性是相对的。例如,在语言级别,您可以不阻止模块形式消耗 100% 的 CPU 或消耗所有内存,直至 OutOfMemoryException
。此类问题需要通过其他方式解决,通常在操作系统级别,包括虚拟化和配额。
所以我个人的回答是:反射是一种安全风险,但与其他潜在的攻击媒介相比,在实践中并没有那么大。
【讨论】:
+1 用于提供出色的链接。尽管我承认我们所拥有的只是猜测,但我非常不同意您的攻击方案。 感谢您的详细解释。这个问题实际上源于我的另一个问题:***.com/questions/3002714/…。提供的答案另有说明,但我仍然不明白为什么 GSON 会以它的方式做事。我最终编写了自己的小 toJSON 方法,但这种方法对于大型对象来说根本不可接受。这让我想到了最后一个问题:如果不是反思,还有其他方法可以做我想做的事情吗?有什么想法吗? @Legend 显然 GSON 在被禁止时尝试使用AccessibleObject.setAccessible
。我不熟悉 GSON,以及为什么它需要更改访问修饰符。我想如果你想理解的话,你应该看看 GSON 的代码。也许您可以制作自己的 GSON 版本,该版本使用反射但不使用 AccessibleObject.setAccessible
,并确保传递对象以进行序列化,其中所有字段/方法都是公开的。【参考方案2】:
GAE 是一个共享托管环境,托管来自多个用户的 WAR 文件。多个 WAR 文件很可能托管在同一个 JVM 中,因为为每个 WAR 生成一个进程实在是太荒谬了。因此,对每个 WAR 文件进行沙箱化的唯一方法是通过每个 WAR 文件的自定义类加载器。
现在,假设允许反射。您could then walk the classloader hierarchy 并从属于不同用户的 WAR 文件中枚举类/方法。显然,这是一个大问题。
【讨论】:
【参考方案3】:首先,如果您没有安装SecurityManager
,那么您无论如何都不安全。
其次,除非启用了setAccessible()
,否则反射不会打开重大漏洞,并且它本身会受到安全检查(由setAccessChecks
reflection permission 管理)。没有它,虽然您可能知道私有字段或方法存在(尽管它本身需要accessDeclaredMembers
runtime permission),但您无法利用这些知识做任何事情。攻击的最佳选择可能是使用序列化对象,但这完全是“另一个蜡球”。
还要注意,编写安全的安全管理器和类加载器并非易事。如果您不渴望成为超级大师(或者更有可能是令人尴尬的失败程度),最好将这些留给其他人。
【讨论】:
【参考方案4】:我的一个理论是谷歌试图隐藏一些东西。通过禁用Reflection,Google 可以隐藏变量名称、函数调用甚至完整的 API。如果 Google 隐藏了 API 之类的东西,那么他们肯定不会告诉你这件事。
我知道反射在安全测试中起着非常重要的作用。例如,您可以使用反射自动生成 Fuzz 测试。 AxMan 使用 TypeLib 来识别构成 COM 对象的所有类及其方法调用。使用此信息,AxMan 将实例化每个类并使用长字符串和大数字的排列调用每个方法。 SOAP Fuzzers 使用 WSDL 文件进行反射进行类似的测试。
【讨论】:
【参考方案5】:应用程序可以使用 Java 反射 API 访问和更新字段,并执行普通 Java 访问/可见性规则禁止的方法。稍加匠心,这足以:
访问本应隐藏的信息, 颠覆 Java 安全沙箱,以便您可以干扰 JVM 中运行的其他事物、访问本地计算机上的文件等等。在某些情况下,它甚至可能允许注入恶意本机代码。
【讨论】:
有趣,你能提供更多细节吗?也许是一个链接。以上是关于对象反射的安全风险是啥?的主要内容,如果未能解决你的问题,请参考以下文章
实施 Restful 管理区域的 Angular 安全风险是啥?