我们知道优先选择char []而不是java.lang.String来存储密码。这是出于以下两个原因(正如我所读):
但是java.sql.DriverManager没有符合上述最佳实践的getConnection(),因为它的密码参数是String。
DriverManager.getConnection(String url,String user,String password)
我认为API应该有一个带有以下签名的重载方法:
DriverManager.getConnection(String url,String user, char [] 密码)
您如何看待这个?你有没有看到任何替代方法来克服这种退缩?
很想听听你的想法。
答案 0 :(得分:4)
String literals 进入池中,但我不希望密码是文字(在程序中硬编码)。我希望它来自配置或类似。因此,它不会是文字,将收集垃圾(如果所有引用都被分箱)。
答案 1 :(得分:3)
你提出了一个很好的观点,大多数人都回答错过了。最糟糕的情况是,操作系统会更换“临时”密码,明文时请注意。在此之后,这个交换文件很容易被读取,如果攻击者有大约1500美元的设备,在磁盘上甚至可以被零覆盖...
你可以做的最好是connect,password = null,然后显式调用gc()。如果幸运的话,这将清除驱动程序实现使用的字符串。
任何方式......
现实情况是,除非平台是专门为安全而设计的,否则所有方法都只是拖延战术。做,你能做什么,但如果确定的人可以访问你的机器,char []最多可以获得1小时。
答案 2 :(得分:2)
除非您可以询问API的设计者,否则只能推测。
我的猜测是:
使用char[]
代替String
的密码,我知道的密码是JPasswordField
。这样做是为了允许程序在使用了值后用其他值覆盖用户输入的密码(String
无法使用</speculation>
,这将至少在内存中停留 直到它被垃圾收集。)
在我所知道的大多数应用程序中,用于连接数据库的密码通常不是用户输入的,而是来自某种配置/目录/...
无论它来自何处:应用程序能够在不再知道后重新构建它。这是用户输入的密码与以编程方式获取的密码之间的巨大差异。
由于密码通常可以通过更简单的方式获取,而不是搜索程序使用的所有内存,因此修复此攻击向量不是一个高优先级
{{1}}
答案 3 :(得分:2)
你的理由#2是我见过的最常用的字符串使用char []。但是,一般来说,我认为如果你假设某人可以通过调试器或其他方式访问你的程序状态,那么他们也没有理由不查看char []的内容。
答案 4 :(得分:2)
使用char []数组的参数适用于用户键入密码的大部分,并且您希望最大限度地减少密码的曝光。
JDBC连接几乎从不那样。密码存储在某些配置文件中,可能是模糊处理的,并且是泄漏源,而不是读取内存的可能性。
无论如何,JDBC标准允许在属性对象甚至URL中传递密码,所以我认为使用char[]
密码参数会给你一种错误的安全感。
如果你有一个真正的用例需要尽可能快地从内存中删除密码以使其无法恢复,并且在真正的JDBC应用程序的上下文中有其他意义,我很乐意听到它。我可以想象这样的事情可能存在,但我想不出使用char[]
确实使事情更安全的情况。
答案 5 :(得分:1)
你的观点1在某种程度上是有效的,但关于字符串结束在未收集的字符串池中的第2点仅适用于静态文字字符串(直接出现在代码中的字符串)。如果您将密码直接存储在您的代码中,我建议首先担心这些密码,因为在类文件中找到密码要比在正在运行的VM中更容易。
因此,如果您认为必须将密码存储在char []中,则在调用getConnection()之前仍可以从中创建String对象。如果驱动程序实现没有在内部存储字符串对象,则它将很快无法访问,因此可以非常快速地收集。当时仍然只能读取它的唯一机会是直接检查JVM的内存。所以你是对的,使用char []会更安全,但不是很多,因为无论如何密码都必须在内存中。
即。使用任何类型的API获取密码的一种非常简单的方法是注入伪造的SQL驱动程序并直接在connect方法中获取密码。无论谁能够检查JVM内存以找到尚未覆盖的密码字符串,也可以注入修改后的驱动程序jar。