76

I have a java application that connects to a database.
The user name and password for the database are stored in a properties file.
What is the common practice to avoid storing the password in cleartext in the properties file while still retaining the option to let the user change it?
The main motivation here is to prevent someone looking over the admin's shoulder and seeing the password while the admin is editing the properties file.
I read here that there's a built in way to do it in C#.
Knowing java, I don't expect to find a built in solution but I'd like to hear what other people are doing.
If I don't find any good choice then I am probably going to encrypt it with a constant password that will be kept in the code. But I'd hate to do it this way because it feels wrong.

Edit Dec 12th 2012 Looks like there is no magic and I must store the password in the code or something similar. At the end we implemented something very similar to what Jasypt that was mentioned in one of the answers does. So I'm accepting the Jasypt answer because it is the closest thing to a definite answer.

Community
  • 1
  • 1
daramasala
  • 3,040
  • 2
  • 26
  • 33
  • 3
    The best you can hope for is obfustication, if the program can read it, anyone with access to the files can too. That's not to say you cant make it damn hard to access. – lynks Apr 24 '12 at 22:11
  • Encrypting it with a constant password that is kept in the code seems like a legit way of doing it if people looking over the admin's shoulder are the main threat. – ZeroOne Apr 24 '12 at 22:20
  • How many people access the database? Don't they need a password for the core database access? Why should you store a second one/ this one? – user unknown Apr 24 '12 at 22:22
  • @userunknown, obviously the Java application needs its own username and password for accessing the database. These are kept in the properties file, like the original poster explained. – ZeroOne Apr 24 '12 at 22:23
  • @ZeroOne: For databases I use, I have an account, and the application just forwards my login information to the database, which grants me privileges or not. Manipulation of a front end program seems to me very risky. – user unknown Apr 24 '12 at 22:30
  • @userunknown Think of a web application like Stack Overflow. The application needs to access a database, but your login credentials to the web site certainly won't let you in into that database that powers the site. The application has its own database credentials. – ZeroOne Apr 24 '12 at 22:40
  • @ZeroOne: `Java application` isn't a web-application, is it? Maybe it is, but then it is poorly specified. – user unknown Apr 24 '12 at 22:48
  • @userunknown Yeah, I just noticed that I just assumed it was. That's because that's the only reason I could think of why anyone would want to save a database password into a properties file. Otherwise it should be done just like you already said. – ZeroOne Apr 24 '12 at 22:51
  • Thanks for all the comments. So, I wonder, if all I can do is obfuscate then I can just encode it in Base64, no? This way it is hard to tell what is the password by looking at it and yet I don't need to use encryption/decryption which seem an overkill given the fact the password is not really secured. – daramasala Apr 30 '12 at 08:00
  • 2
    I created an opensource-library: http://secured-properties.brabenetz.net/ Please let me know what you think about it. – Harald Brabenetz Nov 01 '16 at 18:08

4 Answers4

58

enter image description here

Jasypt provides the org.jasypt.properties.EncryptableProperties class for loading, managing and transparently decrypting encrypted values in .properties files, allowing the mix of both encrypted and not-encrypted values in the same file.

http://www.jasypt.org/encrypting-configuration.html

By using an org.jasypt.properties.EncryptableProperties object, an application would be able to correctly read and use a .properties file like this:

datasource.driver=com.mysql.jdbc.Driver 
datasource.url=jdbc:mysql://localhost/reportsdb 
datasource.username=reportsUser 
datasource.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm) 

Note that the database password is encrypted (in fact, any other property could also be encrypted, be it related with database configuration or not).

How do we read this value? like this:

/*
* First, create (or ask some other component for) the adequate encryptor for   
* decrypting the values in our .properties file.   
*/  
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();     
encryptor.setPassword("jasypt"); // could be got from web, env variable...    
/*   
* Create our EncryptableProperties object and load it the usual way.   
*/  
Properties props = new EncryptableProperties(encryptor);  
props.load(new FileInputStream("/path/to/my/configuration.properties"));

/*   
* To get a non-encrypted value, we just get it with getProperty...   
*/  
String datasourceUsername = props.getProperty("datasource.username");

/*   
* ...and to get an encrypted value, we do exactly the same. Decryption will   
* be transparently performed behind the scenes.   
*/ 
String datasourcePassword = props.getProperty("datasource.password");

 // From now on, datasourcePassword equals "reports_passwd"...
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
  • 18
    So, basically, now password is hard-coded in the program? – mazaneicha Apr 25 '12 at 03:50
  • 13
    The "password" that you see in the example is used to perform the encryption/decryption of the values. In this example it is hard-coded, but it could be retrieved from anywhere(e.g. environment variable). However, the property value(s) that you don't want to be stored plain-text are **encrypted** and then decrypted when read through the `getProperty()` method. It is basically a layer of obvuscation, but does address the issue of shoulder surfing and casual access to sensitive data at rest. – Mads Hansen Apr 25 '12 at 10:48
  • 1
    @MadsHansen Thanks for the info. I don't think I'll use it for this project (already too far into code freeze...) but I will certainly remember it for next version/project. – daramasala Apr 30 '12 at 08:02
  • @MadsHansen How should I encrypt the password into encrypted code like ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm) ? – Kedron Nov 11 '14 at 08:40
  • 1
    @Kedron u can do this like StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword("abhinav"); String encryptedPassword = encryptor.encrypt("abc@123"); System.out.println(encryptedPassword); if ("abc@123".equals(encryptor.decrypt(encryptedPassword))) { System.out.println("Success"); } else { System.out.println("Failure"); } – gladiator Nov 28 '14 at 11:51
  • For just a couple of properties this is overkill. Just read the sensitive parts from System.getProperties() and provide them with -D on the command line when you start your Java process. The problem with shell history and over the shoulder peeking is just as serious if you provide the Encryptors password on the command line. – Glenn Bech Sep 02 '15 at 09:45
  • 2
    Is there a way to secure "password" ? :D – Pasupathi Rajamanickam Jul 13 '17 at 02:14
  • How is it going to work with SpringBoot? In SpringBoot, we directly user the properties value instead of using FileInputStream.. Kindly suggest. – Rohit Apr 19 '18 at 13:08
  • 1
    @Rohit - take a look at https://github.com/ulisesbocchio/jasypt-spring-boot to see what they have done, and if you might be able to leverage – Mads Hansen Apr 19 '18 at 14:26
12

The poor mans compromise solution is to use a simplistic multi signature approach.

For Example the DBA sets the applications database password to a 50 character random string. TAKqWskc4ncvKaJTyDcgAHq82X7tX6GfK2fc386bmNw3muknjU

He or she give half the password to the application developer who then hard codes it into the java binary.

private String pass1 = "TAKqWskc4ncvKaJTyDcgAHq82"

The other half of the password is passed as a command line argument. the DBA gives pass2 to the system support or admin person who either enters it a application start time or puts it into the automated application start up script.

java -jar /myapplication.jar -pass2 X7tX6GfK2fc386bmNw3muknjU

When the application starts it uses pass1 + pass2 and connects to the database.

This solution has many advantages with out the downfalls mentioned.

You can safely put half the password in a command line arguments as reading it wont help you much unless you are the developer who has the other half of the password.

The DBA can also still change the second half of the password and the developer need not have to re-deploy the application.

The source code can also be semi public as reading it and the password will not give you application access.

You can further improve the situation by adding restrictions on the IP address ranges the database will accept connections from.

Abelgo Japan
  • 137
  • 1
  • 3
  • 2
    This might not be secure. Providing credentials via command line is not generally recommended due to OS logging. An intruder will just open the source file -> read half of the password, then type `history` in command line and voila! – Kostas Kryptos Dec 01 '17 at 10:46
  • This is "better", but I agree with commenter K.C.........it can still be found-out with a lot of perseverance. – granadaCoder Aug 27 '18 at 15:28
10

What about providing a custom N-Factor authentication mechanism?

Before combining available methods, let's assume we can perform the following:

1) Hard-code inside the Java program

2) Store in a .properties file

3) Ask user to type password from command line

4) Ask user to type password from a form

5) Ask user to load a password-file from command line or a form

6) Provide the password through network

7) many alternatives (eg Draw A Secret, Fingerprint, IP-specific, bla bla bla)

1st option: We could make things more complicated for an attacker by using obfuscation, but this is not considered a good countermeasure. A good coder can easily understand how it works if he/she can access the file. We could even export a per-user binary (or just the obfuscation part or key-part), so an attacker must have access to this user-specific file, not another distro. Again, we should find a way to change passwords, eg by recompiling or using reflection to on-the-fly change class behavior.

2nd option: We can store the password in the .properties file in an encrypted format, so it's not directly visible from an attacker (just like jasypt does). If we need a password manager we'll need a master password too which again should be stored somewhere - inside a .class file, the keystore, kernel, another file or even in memory - all have their pros and cons.
But, now users will just edit the .properties file for password change.

3rd option: type the password when running from command line e.g. java -jar /myprogram.jar -p sdflhjkiweHIUHIU8976hyd.

This doesn't require the password to be stored and will stay in memory. However, history commands and OS logs, may be your worst enemy here. To change passwords on-the-fly, you will need to implement some methods (eg listen for console inputs, RMI, sockets, REST bla bla bla), but the password will always stay in memory.

One can even temporarily decrypt it only when required -> then delete the decrypted, but always keep the encrypted password in memory. Unfortunately, the aforementioned method does not increase security against unauthorized in-memory access, because the person who achieves that, will probably have access to the algorithm, salt and any other secrets being used.

4th option: provide the password from a custom form, rather than the command line. This will circumvent the problem of logging exposure.

5th option: provide a file as a password stored previously on a another medium -> then hard delete file. This will again circumvent the problem of logging exposure, plus no typing is required that could be shoulder-surfing stolen. When a change is required, provide another file, then delete again.

6th option: again to avoid shoulder-surfing, one can implement an RMI method call, to provide the password (through an encrypted channel) from another device, eg via a mobile phone. However, you now need to protect your network channel and access to the other device.

I would choose a combination of the above methods to achieve maximum security so one would have to access the .class files, the property file, logs, network channel, shoulder surfing, man in the middle, other files bla bla bla. This can be easily implemented using a XOR operation between all sub_passwords to produce the actual password.

We can't be protected from unauthorized in-memory access though, this can only be achieved by using some access-restricted hardware (eg smartcards, HSMs, SGX), where everything is computed into them, without anyone, even the legitimate owner being able to access decryption keys or algorithms. Again, one can steal this hardware too, there are reported side-channel attacks that may help attackers in key extraction and in some cases you need to trust another party (eg with SGX you trust Intel). Of course, situation may worsen when secure-enclave cloning (de-assembling) will be possible, but I guess this will take some years to be practical.

Also, one may consider a key sharing solution where the full key is split between different servers. However, upon reconstruction, the full key can be stolen. The only way to mitigate the aforementioned issue is by secure multiparty computation.

We should always keep in mind that whatever the input method, we need to ensure we are not vulnerable from network sniffing (MITM attacks) and/or key-loggers.

Community
  • 1
  • 1
Kostas Kryptos
  • 4,081
  • 2
  • 23
  • 24
0

Actually, this is a duplicate of Encrypt password in configuration files.

The best solution I found so far is in this answer: https://stackoverflow.com/a/1133815/1549977

Pros: Password is saved a a char array, not as a string. It's still not good, but better than anything else.

Joe Taras
  • 15,166
  • 7
  • 42
  • 55
Benjamin Marwell
  • 1,173
  • 1
  • 13
  • 36