Java 中的断言不安全吗?

Are Assertions Insecure in Java?

在 C# 中,编译器可以通过从调试模式切换到发布模式来去除断言。从安全(和用户体验)的角度来看,这是一件好事,可以避免将堆栈跟踪暴露给最终用户,as a stacktrace may lower user-confidence in the stability of the app, and a stacktrace could expose vulnerabilities which can be exploited。此外,堆栈跟踪可以提供一些信息,帮助黑客对软件进行逆向工程。

查看 Java 断言后,似乎不存在这种能力。也就是说,断言保留在已编译的字节码中,Java 编译器没有命令行选项可以将它们删除。相反,我们看到 Java runtime permits the enabling of assertions, something which could be done by a malicious user attempting to glean stacktrace information. Also, I've even seen some encourage the idea that assertions should fail dramatically 吐出一个 AssertionError 和一个堆栈跟踪。或者简单地说,人们忽略了让应用程序像这样失败的安全方面。

我的初步评估是 Java 中的 断言会带来安全风险 ,即使它们为调试提供了优势或维护。

我们是否应该避免在 Java 中对安全关键应用程序使用断言?或者如果有一个正确的、安全的方法包含断言,应该怎么做?


为清晰起见编辑: 我在这里假设 Java 应用程序作为桌面应用程序部署到最终用户。也就是用户downloads/installs的应用。话虽如此,据我了解,用户能够 运行 一个可执行 jar,同时启用具有以下效果的断言:

java -ea -jar "MyJar.jar"

断言不会使 Java 程序的安全性降低到现在的水平。并不是说它会是 Java 的 "feature",因为在您的计算机上用任何语言 运行 编写的任何程序都是不安全的,除非您可以利用 TPM 之类的东西(即使那样它也是不完全安全,除非你相信营销人员)。

您没有义务向用户显示堆栈跟踪,但这与安全性关系不大。将其写入日志要干净得多。您也没有义务使用断言,我认为与例如 C# 相比,它在 Java 生态系统中可能不太常见。


堆栈跟踪本身在桌面环境中提供的有用信息非常少¹,因为无论如何您已经拥有对代码的完全访问权限。有许多比使用断言尝试欺骗更容易收集信息的方法。对于其中之一,您可以反编译 类。现在您可能会认为 "I'll obfuscate it, at least it will make it a bit harder",但这等同于说 "I'll build a very low fence, at least it will keep babies away"。它不比没有好,它什么都没有,但它会让你认为你有一定程度的保护,这是一个安全风险。

要么您有需要保护的信息并且必须使用有效的方法,要么您有不重要的信息并且不需要保护它。虽然安全端有不同的风格和要求,但通常使用 fancy government names.

¹ 在 Web 环境中,向用户显示堆栈跟踪可能存在安全风险,因为它可以显示有关正在使用的库的信息,并通过库错误提供攻击向量。这就是为什么您在生产环境中看不到堆栈跟踪的原因,除非有人把事情搞砸了。

Rather, we see that the Java runtime permits the enabling of assertions, something which could be done by a malicious user attempting to glean stacktrace information.

如果用户能够在 JVM 运行 安全性有问题的应用程序中启用断言,则他们已经具有允许他们实现更重要的攻击的访问级别。

向最终用户公开堆栈跟踪确实会带来安全隐患,但是否以这种方式公开堆栈跟踪是应用程序设计人员可以控制的事情。

Should we stay away from using assertions in Java for security-critical applications; or if there is a proper, and secure, way include assertions, how should it be done?

我认为出于安全原因避免使用断言的一个很好的论据是程序员可能会不小心使用具有副作用的断言条件。如果程序是在启用断言的情况下开发和测试的,但在未启用断言的环境中发布,则程序的行为将有所不同。这可能会引入可能造成安全漏洞的错误。