2

I'm working on a small web application. The web application needs access to a database, so the application needs access to a database username and password.

The application runs in an environment where virtual machines comes and goes and there are no persistent disks. The only environment configuration we can set up which remains over time are certificates, all other configuration must be stored as a part of the application (which we upload to the hosting service in a zip). Certificates which we upload to the hosting providers are automatically installed into the Windows certificate store by the hosting provider.

The database server we are using do not support authentication using certificates - only user name and passwords, so I'm wondering if the following scheme would make sense:

  1. We create a self-signed X509 certificate using openssl or makecert.
  2. We upload the certificate (with private key) to the hosting provider (we do this once, or when we want to renew the certificate).
  3. We encrypt the database passwords in the application configuration using the public key-part of our certificate (using RSACryptoServiceProvider).
  4. We upload the encrypted password in a configuration file as part of our application package zip to the provider
  5. In our application code, before connecting to the database server, we decrypt the database password using the certificate (again, using RSACryptoServiceProvider)

With this, we get the following:

  1. Anyone (me or my friends) working with the application can set a new database password, encrypt it and update the application configuration, without access to the private key in the certificate.
  2. Only people with the private key (which is installed on the servers and stored locally by me) can decrypt the database password.

It seems like this would be a pretty good solution, but I would appreciate if someone else could spot a flaw.

  • When you say a "certificate", what type of certificate are you referring to specifically? How is this certificate created in the first place? – Nic Barker Sep 1 '15 at 7:05
  • It would be a self-signed X509 certificate specifically created to be used only for this purpose. I have not created one yet, but I assume it should be easy using the openssl or makecert command line tools (clarified this in the OP) – Nitramk Sep 1 '15 at 7:13
3

On the surface this sounds like a fine idea - if you're trying to provide a buffer against:

  • Version control (git / svn hosting) compromise
  • Theft of a physical machine containing the codebase / credentials
  • Malware on one of your developers machines leaking the credentials in some way.
  • Any other way in which the files containing credentials are stolen by an attacker

Just remember that this wont protect your database if your web app itself is compromised, as it will still have the unencrypted credentials in memory at some point. If you're just trying to protect the credentials from being stolen from somewhere other than the live machine this should work just fine, though.

Also, in my opinion the environment that you're describing sounds quite non standard, which worries me a little. You're relying on whatever service the hosting provider is exposing to access the private keys in a big way.

  • The hosting provider in this case is Microsoft Azure and I've already chosen to trust them with the data for this specific project. I agree with your statement regarding non-standard, but I haven't really been able find a standard way to handle this. This site, StackOverflow and other sites contains a bunch of posts in this area, but I haven't really seen a clear "this is the proper way to implement this.". Some argue that the proper way is to pass it as command line arguments when starting the app, but that's not possible in an environment where machines come and go without our control. – Nitramk Sep 1 '15 at 8:22
1

Its not clear to me if you're using Azure VM or PaaS but you may want to consider a flow using SAS tokens.

On Azure you have a built-in mechanism called SAS -shared access signatures. You can read more about SAS here https://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-shared-access-signature-part-1/

Your flow would be like this

  1. Pass credentials and get a timed one time SAS token
  2. You can use SAS with functional granularity - ie - different tokens for different data operations. This will give you a great solution using native Azure functionality

While the vulnerability of storing a username/password in your backend code exists - if an attacker compromises physical machine/your VM or exploits your code and elevates permissions then using public/private key scheme as you describe will not be an effective security countermeasure and will only cost you a lot of grief and time testing and debugging. So forget it. Code your credentials in the code and use SAS

In general - I would do a threat analysis on your application before implementing security countermeasures and also as a best practice never DIY cryptography!

  • Thanks. But SAS tokens only applies to Azure Storage, not to Azure SQL Database. Azure SQL Database has nothing like that. While I agree that encrypting secret data will not prevent all types of attack, it will prevent some versions of it. For example, the application zip I'm referring to - which we have to put together - would not contain the secret. So if our build environment was hacked, then that would not help an attacker because the password is not in the source anyway. It would also stop basic file inclusion vulnerabilities where an attacker manages to gain access to f.ex app.config. – Nitramk Sep 1 '15 at 10:30
  • Also - I agree that you should not implement cryptography yourself. But encrypting a secret using standard .NET functionality isn't really reinventing the cryptography wheel yourself in my opinion. And I don't see how it could make things worse from a security point of view than your suggested approach of storing it in clear text? – Nitramk Sep 1 '15 at 10:32
  • Of course it will make it worse. Your scheme will need to be developed and debugged and it will almost certainly introduce new vulnerabilities neither you nor I thought of. KISS - keep it simple. I would be more concerned about someone hacking your VM - and Azure has oodles of best practices for that. – Danny Lieberman Sep 1 '15 at 10:40
  • So the alternative is to store the password in clear text in location X, or to store it as encrypted in location X. And you're arguing that storing it in plain text will be more secure than storing it encrypted? If the password is stored in the same location, I'm having a hard time seeing how storing it as plain-text would be more secure than encrypted. – Nitramk Sep 1 '15 at 10:48
  • Not sure I understand your environment. Unless I'm mistaken, you are using an Azure VM and you have control of persistent storage on your disk. Consider your threats: Threat 1 - someone steals your VM. Probablity 0. Threat 2 - Elevation of privilege attack, using certificates won't help. \n You said it's a small Web app. KISS - keep it simple Use Windows integrated security and you won't have to store credentials in clear text. – Danny Lieberman Sep 1 '15 at 10:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.