Setting Java system properties without putting values ​​on the command line

I have Java code that depends on the system property super.secret.password . I need to set this property when I launch my application. The application will be launched by the shell script, and the password will be stored in a file with minimal read permissions.

I really don't want to write:

 java -Dsuper.secret.password=letmein gov.fortknox.MyApp 

Because then anyone who can go to the machine and run ps or top can see what a password is.

So, is there a good way to set system properties without exposing them on the command line?

The only general solution we came up with is to write a small C program that reads the system properties from a file, then runs the JVM using the JNI API calls . Needless to say, we are not striving to do this.

If there is no way to install them without using the command line, is there a way to hide the command line from prying eyes? We are using Red Hat Enterprise Linux Server 5.5.

For what it's worth, the application in question is actually JBoss EAP 4.3.0, and we use the system properties to populate the substitution constructs ( ${like.this} ) in the XML configuration files. There are specific JBoss solutions β€” either use the SystemPropertiesService (by default, configured through the properties-service.xml file in the deployment directory) or pass in - option P to run .sh. However, I am interested in the more general case when it can be any Java program.

+6
source share
6 answers

You can simply read the file somewhere near the start and call System.setProperty() . For a web application, use the ServletContextListener for this to happen earlier, see this answer for a quick example.

Update: maybe it is not too early for your use when JBoss loads configuration files.

+3
source

If your concern reveals the value of super.secret.password in text form, but you do not care that someone ran your program with the correct password value because you addressed this problem using permissions or some other means, then I think you could just encrypt the password in your startup script and have a shell class, decrypt it.

 java -Dsuper.secret.password=BbWvOuliHZVHVwsXudsj14d1iXzo655R gov.fortknox.DecryptWrapper 

If the credentials are for a data source, I must also specify other JBoss- specific solutions: SecureIdentityLoginModule , which essentially do this, and PBEUtils , which offers a keystore solution when used with SecureIdentityLoginModule . See EncryptingDataSourcePasswords .

Finally, Peter Lawery’s suggestion to use the file is also valid.

+3
source

'cryptomainia' was written to solve this exact problem. It decodes the arguments to main (). https://github.com/birchb1024/cryptomainia

+1
source

You can read it from some file in the static initializer of your class, which contains the main method:

  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(...){ ... } 
+1
source

You can use the JAVA_TOOL_OPTIONS environment variable and set the property there. But it will be visible even in your script file.

0
source

if an attacker has physical access to your machine, then there is no real reason why they cannot own the machine - a simple rot13 to prevent an accidental eye is a lot.

If the attacker has some privileges (for example, running from above), but not physical access, you can run the program under a specialized user account (for example, a web server-user), which has very few privileges but has exclusive read access to file containing the password. you then launch the application using this account and transfer the file path.

It depends on OS access privilege restrictions, which are likely to be implemented much better than what you can overturn.

0
source

Source: https://habr.com/ru/post/886228/


All Articles