How to keep secrets secret
(Alternatives to Hardcoding Passwords)
"Hardcoding passwords" is a short name for putting non-encrypted (plain text) passwords and other secret data (like private keys etc.) into the source code. Typical examples could be:
private static String passwd = "mYv3rYSECr3tPWD";
db = MySQLdb.connect(host="db.server.com", user="admin", passwd="NOBODYwillEVERguess", db="sales")
String url = "jdbc:mysql://" + serverName + "/access?user=webclient&password=ILoveJuliet";
for i in 01 02 03 04; do ./remove_temp_files.sh --machine=appserv$i --rootpassword="*d3H%sS-W"; done
Although software developers might not realize, in fact their source code is (or becomes) very often publicly available. It might be kept in a Git repository, which is browseable on the Web. Other developers or code maintainers might send out parts of code by e-mail or post in on the Web without being aware that they reveal passwords. Even if source code is kept on a secure file system during development, it will almost certainly be moved around later (maybe some years later), as the team is reorganized, file servers are upgraded etc. - and new locations might not be protected anymore. Compiled program can be easily reverse engineered. And last but not least, passwords should be changed regularly - and changing hardcoded passwords could be a lot of hassle (recompilation of the source code, new release etc.). For all these reasons, software developers should avoid hardcoding secret information (passwords etc.) in the source code.
But what are the alternatives to hardcoding passwords?
What else can developers do?
There isn't one simple solution to this problem, and it has to be solved on case-to-case basis. Below are suggestions of some of the possible solutions:
- Ask the user for a password: In many cases, it is the user who should know the password, not the program! This is the best solution, if only it can be applied (unfortunately, it won't work for batch scripts, web applications connecting to a database etc.);
- Use already existing credentials: For example: AFS and/or Kerberos tokens are available when a script is executed from acrontab;
- Keep secrets in a separate file: It is much easier to guard a separate config/properties file that is known to contain password(s), than to keep an eye on multiple locations of passwords in source code (that might get refactored etc.). Such file should have very restrictive file permissions, and should not end up in Git or Pastebin etc. Watch out: if it is a web application, make sure that the password file is not just downloadadable by everyone! For Puppet managed devices, use CERN IT's "tbag" service;
- Encrypt: If only your program already has/knows a secret (another password, decryption key etc.), you can use it to encrypt (and later decrypt) other secrets information. Libraries providing encryption algorithms like RSA, Rijndael etc. are available for all common programming languages and platforms. Even encrypted, it's better to place the secret data in a separate file (see above);
- Keep secrets in a database: If well protected, database is a good place to safely store passwords. Obviously, it won't work for the passwords that open the database (famous question of what came first, the hen or the egg), so you have to choose another solution;
- Hash users' passwords: If your software stores passwords of your users (clients), keep them hashed instead of in plain text (as described here);
- For Puppet managed hosts: Obviously some data of hosts managed via Puppet needs to be secret, but having these managed directly with Puppet master is insufficiently secure. This document teaches how to do best.
This list contains the most common workarounds to the hardcoded passwords problem. It is not complete and closed - there is probably a lot of other solutions that might suit some specific cases. Please do not hesitate to e-mail Computer.Security@cern.ch if you have any suggestions or remarks concerning the list.