我正在处理一个Java服务,该服务记录了一个安全错误,涉及存储在Java字符串对象中的一个秘密.

令人担忧的是,一旦密码存储在String中,它就会一直留在字符串池中,直到它被垃圾收集,并可能在转储中显示为明文.

我知道Java的String类是不可变的,最好将秘密或密码存储在可变类中,这样在使用后可以尽快将其从内存中删除.

参考文献

然而,在使用第三方库时,我发现这是不切实际的,因为他们中的许多人希望将密码或密码作为字符串对象在请求中传递,无论我多么安全,在我的代码中,最终都会将char[]数组转换为String,这会让我们回到最初的问题,不是吗?

So, is there anyway to convert a 100, or 101 to a 102, without getting back to the original problem?

编辑:正如这个问题和其他类似问题中的 comments 所指出的,许多人认为这并不是一个真正的问题,因为如果你不拥有应用程序中的所有代码(即不向任何第三方库传递机密),就没有简单的方法来避免这个问题.因此,考虑到这一点,也许问题变成了

How can I refute the bug? is there a good solid reference from Oracle/Owasp or whoever that says "unsolvable problem" ?

推荐答案

如果您需要调用需要String的API,则无法避免创建String.只要避免字符串文字或显式驻留的字符串,字符串就不会在字符串池中结束.

这也是一个不可能解决的问题.例如,如果这是数据库连接池的密码,则该密码需要在程序的生存期内可用,才能创建新连接.即使您可以以某种清晰的方式(如char[]CharBufferStringBuilder等)提供密码,也不能保证您正在调用的API不会将其转换为字符串或进行复制等.

即使使用char[]也不能保证您能够正确地将其从内存中清除:Java垃圾回收器可以并将在内存中移动对象,因此您的密码完全有可能仍在内存中以前的位置,即使您显式地将该char[]置零.

如果威胁参与者有足够的权限访问您的系统以判断内存、进行堆转储等,则您有更大的问题,担心使用StringVS char[]只是浪费时间,因为该威胁参与者将有其他方法来找到您的密码,如查找配置源、修改程序以在下一次运行时记录密码等.

需要明确的是,能够快速清除某些敏感信息可以减少攻击窗口,但除非您在高度安全的环境中工作,否则考虑到所有警告,这不太可能是正确的.

Java相关问答推荐

将状态栏和导航栏设置为白色,带有深色文本

Mongo DB Bson和Java:在子文档中添加和返回仅存在于父文档中的字段?

无法在Java中将hhmmss格式的时间解析为LocalTime

确定Java中Math.Ranb()输出的上限

使用Mockito进行的Junit测试失败

基于调车场算法的科学计算器

在Spring终结点中,是否可以同时以大写和小写形式指定枚举常量?

使用OAuth 2.0资源服务器JWT时的授权(授权)问题

如何为JavaFX Spring Boot应用程序制作Windows/MacOS/Linux安装程序

如何将Java文档配置为在指定的项目根目录中生成?

有谁能帮我修一下这个吗?使输出变得更加整洁

FETCH类型设置为LAZY,但它仍会发送第二个请求

将双倍转换为百分比

无法使用Open WebStart Java 8运行jnlp

如何在Selenium上继续使用最新的WebDriver版本

using case default on switch语句返回;预览特征切换中的模式匹配仅在源级别20及以上的情况下可用;

如何在Java中正确实现填字游戏求解器

为什么当我输入变量而不是直接输入字符串时,我的方法不起作用?

睡眠在 Spring Boot 中

类型安全:从 JSONArray 到 ArrayList> 的未经判断的转换