Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for storing passwords that need to be reused?

We have an automation platform that needs to store service account passwords in a database.

These passwords are used in a variety of different cases but generally need to be reversed into their original plain text form in order to be functional.

The service accounts are all compartmentalized to do very specific things - however, I'm uncomfortable leaving them in the database in plain text.

What is the best method/technique for storing passwords in a database when they need to be reversible?

For specific recommendations the platform is using C#, .Net MVC, and MySQL (MariaDB).

My immediate plan would be to store them after signing them with a non-exportable private key held in the local key store on the application server. Then reversing the encryption method when reading them out of the database.

If this is the technique I should be using are there particular methods I should be aware of?

Thank you for any help or information.

[Edited To Re-Open and remove the "Opinion Based" classification. Microsoft had particular documentation for this exact use case. I can't add an answer or mark as answered until it is but my solution is as follows:]

The recommendation from the Microsoft Engineering team was to use the Machine Key class and methods.

Utilizing a machine key set and generated via IIS and a uniquely generated "purposes" string provided to the Protect method I can securely encrypt and decrypt a column and leave it secure while at rest.

In MariaDB (MySQL) you'll need to use a column of tinyblob to store the byte array.

I don't believe this is an opinion based answer since this is the defacto way to do it with the technologies specified in the question.

IIS Machine Key

like image 235
EndOfAll Avatar asked Mar 26 '18 22:03

EndOfAll


1 Answers

Usually, to perform activities on behalf of a user with another service provider, you would use a scheme like OAuth2.

In this case, I assume this is not available or provided.

The issue with encrypting passwords as compared to hashing them is that encryption is a two-way function, it can be reversed, and this is in itself a security issue, since anyone with the key can decrypt the password. The issue then becomes how do I keep the key safe?

The answer is simple: Don't keep the key anywhere on your system.

Use your own users password to derive an encryption key, and then use this to encrypt their other passwords that you are storing for use with other services. When you need these passwords, the user must provide their "master" password to authorize the action

This has the benefit that if your database was compromised, no passwords would be recoverable. Additionally, if your front facing server was compromised, the only attack vector would be to modify the behaviour and wait for users to attempt to login.

From a more technical point of view, do the following:

  • When a user creates an account with you, derive a key from their password (PBKDF2 is a good choice). Let's call this k1.

  • Randomly generate another symmetric key, let's call this k2.

  • Encrypt all external passwords for other services with k2, which you can get each time by deriving k1 again and then decrypting.

  • If the user wants to change their account password, simply decrypt k2 with the old k1, derive a new key from their new password, and encrypt k2 again with the new key.

You should really avoid storing user passwords in a form that is reversible. But if you absolutely have to, the above is a good approach that keeps things relatively secure.

like image 112
Luke Joshua Park Avatar answered Oct 13 '22 00:10

Luke Joshua Park