在C#中,编译器可以通过从调试模式切换到释放模式来消除断言。从安全(和UX)的角度来看,这是一件好事,以避免将堆栈跟踪暴露给最终用户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,可以由恶意用户尝试收集堆栈跟踪信息来完成。另外,我甚至看到一些encourage the idea that assertions should fail dramatically吐出AssertionError
和堆栈跟踪。或者简单地说,人们忽略了让应用程序失败的安全方面。
我最初的评估是,Java中的 断言构成了安全风险 ,即使它们为调试或维护提供了优势。
我们是否应该远离在Java中使用断言来处理安全关键应用程序;或者如果有适当的,安全的方式包括断言,应该怎么做?
<小时/> 编辑清晰度: 我假设Java应用程序作为桌面应用程序部署到最终用户。也就是说,用户下载/安装应用程序。话虽如此,我的理解是,用户能够运行可执行jar,同时启用具有以下效果的断言:
java -ea -jar "MyJar.jar"
答案 0 :(得分:1)
断言不会使Java程序的安全性低于现有程序。并不是说它是Java的“功能”,因为任何使用计算机上运行的语言编写的程序都是不安全的,除非你可以利用像TPM这样的东西(即使那时它并不完全安全,除非你相信营销人员)。
您没有义务向用户显示堆栈跟踪,但这与安全性几乎没有关系。将它写入日志更加清晰。您也没有义务使用断言,我认为与C#相比,Java生态系统中可能不太常见。
堆栈跟踪本身在桌面环境中提供的信息很少¹,因为您已经拥有对代码的完全访问权限。收集信息比使用断言尝试欺骗有许多简单的方法来收集信息。对于一个你可以反编译的类。现在你可能会认为“我会混淆它,至少它会让它变得更难”,但这相当于说“我会建造一个非常低的栅栏,至少它会让婴儿远离它们”。它并不比什么都好,它 什么都没有,但它可以让你认为你有一定程度的保护,这是一个安全风险。
您要么拥有需要安全的信息,又必须使用有效的方法,要么您拥有的信息并不重要,您无需保护它。虽然安全端具有不同的风格和要求,但标度是二进制的,通常使用fancy government names。
¹在Web环境中向用户显示堆栈跟踪可能存在安全风险,因为它可以显示有关正在使用的库的信息,并通过库错误提供攻击向量。这就是为什么你没有看到生产中的堆栈痕迹,除非有人搞砸了。
答案 1 :(得分:1)
相反,我们看到Java运行时允许启用断言,这可以由试图收集堆栈跟踪信息的恶意用户完成。
如果用户能够在运行安全性有问题的应用程序的JVM中启用断言,那么他们已经拥有一定程度的访问权限,从而可以实现更多的后续攻击。
向最终用户公开堆栈跟踪确实会产生安全隐患,但是应用程序设计人员可以控制是否以这种方式公开堆栈跟踪。
我们是否应该远离在Java中使用断言来处理安全关键应用程序;或者如果有适当的,安全的方式包括断言,应该怎么做?
我认为,出于安全原因避免使用断言的一个好理由是程序员可能会意外地使用具有副作用的断言条件。如果程序是在启用断言的情况下开发和测试的,但是在没有断言的环境中发布,则程序的行为将会有所不同。这可能会引入可能带来安全漏洞的错误。