从 JVM 堆中删除密码

Eliminating Passwords from the JVM Heap

关于如何在 Java 代码中管理密码的各种问答 - 例如,here and here

讨论往往集中在使用 char[] 而不是 String 的优点上。

但是,如果是将密码存储在字符串中的第 3 方库,是否有任何方法可以避免将密码存储在 JVM 的堆中?

例如,在以下三种情况下,我认为密码将在 JVM 的生命周期内保留在堆中:

Hikari 连接池 3.4

编辑 - 示例更新为与我的问题更相关:

// some values read in from a properties file, or similar:
String url = ...;
String user = ...;
String pw = ... ;
...
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(url);
ds.setUsername(user);
ds.setPassword(pw);
...

在上面的示例中,我的 com.zaxxer.hikari.HikariDataSource 对象包含 String 中的密码。我找不到在不丢失连接池的情况下使数据源为空的方法。

Jetty 9.4 数据库适配器

例如,如果我创建一个 JDBCSessionDataStoreFactory,那么 org.eclipse.jetty.server.session.DatabaseAdaptor 会保留连接凭据,包括 String 中的密码。

Tomcat9 中的 JNDI 连接

在这种情况下,密码可以在 org.apache.tomcat.util.descriptor.web.ContextResource 中找到,如果我也选择使用该连接池,也可能在 org.apache.tomcat.dbcp.dbcp2.BasicDataSource 中找到。

换句话说,敏感的连接信息可以在我的 JVM 堆中的不同位置找到,无论我在我的代码中使用 char 数组和 overwriting/nulling 不再需要的敏感数据时多么勤奋。我并不是说我的努力是白费的——我仍然想保护我能保护的东西(例如用户的登录凭据)。但是其他凭证,例如数据库连接,似乎不在我的控制范围内。

是否有针对这些情况的解决方案或最佳实践?

正如@Holger 在评论中所说,任何可以读取您的堆内存的东西 and/or 文件系统中的堆转储,已经控制了服务器,因此此时尝试隐藏密码是无用的.最好致力于保护其中的实际服务器和服务。

Thomas Porning 在下面的 link 中给出了很好的答案,但这是关键段落(突出显示我的):

None of this applies to a server application, or to client code that handles secrets with an actual non-negligible value. If a malicious attacker is in position to scan the RAM for sensitive data, and that data is worth 1 or 2 minutes of explicit attention from the human attacker, then no amount of overwriting will save you. Thus, in many contexts where security matters, overwriting of passwords and keys is just wasted effort, that gives a feeling of security, but does not actually improves things (though it may be convenient to awe auditors).

https://security.stackexchange.com/a/75891/4667