我正在维护一个现有的Java产品(它有一个庞大的代码库)。我发现它在不少于4-5个不同的地方(方法)将两个内部密码设置(并获取)为Java系统属性。现在的问题是,密码以明文形式存储在Java系统属性中,因此,外部实体也可以看到密码,因为应用程序没有使用任何Java Security Manager。例如,如果应用程序(进程)在端口号1234上运行,我们可以运行Java命令:
jinfo -sysprops 1234
以将两个密码都视为相应Java系统属性的值。我想问一下,在不对现有代码库进行过多更改的情况下,是否有任何补救措施?期望的效果是对所有外部实体"隐藏"两个Java系统属性(表示两个密码)。
需要注意的是,在应用程序中引入Java Security Manager可能不是一个解决方案,因为如果我们使用Java Security Manager吊销上述两个Java系统属性的读取权限,读取这些属性的应用程序代码就会崩溃。同样适用于以加密形式存储密码,因为这会导致应用程序中所有希望以明文形式读取密码的代码崩溃。
既然你说了:
在不少于4-5个不同的地方。。。
如果你真的不想做重大的代码更改,我会:
- 以加密形式提供密码
- 浏览这4-5个地方(没有那么多!),并调用一个必须单独编写的包装器方法:
MyPassUtil.getXYZPassword()
,它在内部调用System.getProperty()来获取加密的密码,解密它,并将纯文本版本返回给调用它的人
不过,请记住,通过这种方式,解密密钥和算法存储在应用程序中,一个好的Java反编译器(JD-GUI或CFR)仍然会返回这些信息。换句话说,任何有权访问JAR文件的人,仍然可以通过一些小的努力来获得信息,我认为,由于可以调用jinfo
,他们也可以获得JAR文件。
最好的方法是使用某种形式的密钥库,同样,一旦完成步骤2中提到的包装方法,就可以轻松地实现它,而不会影响使用它的人
此外,一些安全提示:
如果是SSH/SFTP连接,请在两台机器之间设置SSH密钥,并消除密码的使用。
如果是数据库连接,至少要将DBMS配置为只允许来自该特定机器的IP地址的连接。如果连接是通过互联网进行的,并且您处于NAT之后,请首先设置VPN,并通过它在主机之间传输流量。
对于其他设置,试着看看是否有其他技巧可以与这两点类似,以提高这些密码的安全性。