我有一些Java代码,它依赖于系统属性super.secret.password
。我需要在运行我的应用程序时设置该属性。该应用程序将由shell脚本启动,密码将保存在具有最小读取权限的文件中。
我真的不想写:
java -Dsuper.secret.password=letmein gov.fortknox.MyApp
因为任何可以登录计算机并运行ps
或top
的人都可以看到密码是什么。
那么,有没有一种很好的方法来设置系统属性而不在命令行上公开它们?
我们提出的唯一通用解决方案是编写一个从文件中读取系统属性的小型C程序,然后使用JNI invocation API启动JVM。不用说,我们并不热衷于这样做。
如果没有办法在不使用命令行的情况下设置它们,有没有办法隐藏命令行?我们正在使用Red Hat Enterprise Linux Server 5.5。
对于它的价值,有问题的应用程序实际上是JBoss EAP 4.3.0,我们正在使用系统属性在其XML配置文件中填写替换构造(${like.this}
)。有JBoss特定的解决方案 - 使用SystemPropertiesService(默认情况下,通过deploy目录中的properties-service.xml文件配置)或将-P option传递给run.sh.但是,我对更一般的情况感兴趣,这可能是任何Java程序。
答案 0 :(得分:3)
您可以在启动附近的某个地方阅读该文件并致电System.setProperty()
。对于Web应用程序,请使用ServletContextListener
,以便及早发生,请参阅this answer以获取快速示例。
更新:对于JBoss加载配置文件的用例,这可能还不够早。
答案 1 :(得分:3)
如果您的问题是以明文形式公开super.secret.password
的值,但您并不担心某人使用正确的密码值调用您的程序,因为您已使用权限或其他方式解决了该问题,那么我认为你可以简单地加密你的启动脚本中的密码,并让一个包装类解密它。
java -Dsuper.secret.password=BbWvOuliHZVHVwsXudsj14d1iXzo655R gov.fortknox.DecryptWrapper
如果凭据是针对数据源的,我还应该指出特定于 JBoss 的其他解决方案:SecureIdentityLoginModule
基本上执行上述操作,PBEUtils
提供了与SecureIdentityLoginModule
一起使用时的密钥库解决方案。见EncryptingDataSourcePasswords。
最后,Peter Lawery使用文件的建议也是有效的。
答案 2 :(得分:1)
'cryptomainia'是为解决这个问题而编写的。它解密main()参数。 https://github.com/birchb1024/cryptomainia
答案 3 :(得分:1)
您可以从包含main方法的类的静态初始值设定项中的某个文件中读取它:
static {
try {
FileReader fr = new FileReader(FILE_NAME);
// read the property
System.setProperty(property.getName(), property.getValue());
} catch (final FileNotFoundException ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
} catch (final IOException ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
...
public static void main(...){
...
}
答案 4 :(得分:0)
您可以使用JAVA_TOOL_OPTIONS环境变量并在那里设置属性。但它仍会在您的脚本文件中可见。
答案 5 :(得分:0)
如果攻击者可以物理访问你的机器,那么他们就没有真正的理由不能拥有这台机器 - 一个简单的旋转可以避免随意的眼睛。
如果攻击者具有某些权限(例如运行top),但不具有物理访问权限,那么您可以在专用用户帐户(例如,web-server-user)下执行该程序,该帐户几乎没有权限,但对包含密码的文件具有独占读访问权限。然后,您使用该用户帐户启动应用程序,并传入文件路径。
这样做依赖于操作系统中的访问权限限制,这可能比您自己实施的操作要好得多。