How can I secure passwords stored inside web.config?

I have added the following settings inside my web.config file to initiate an API call to external system. So I am storing the API URL + username + password as follows:-

<appSettings>
    <add key="ApiURL" value="https://...../servlets/AssetServlet" />
    <add key="ApiUserName" value="tmsservice" />
    <add key="ApiPassword" value="test2test2" />

Then inside my action method I will be referencing these values when building the web client as follows:-

public ActionResult Create(RackJoin rj, FormCollection formValues)
        {
           XmlDocument doc = new XmlDocument();
           using (var client = new WebClient())
                {
                    var query = HttpUtility.ParseQueryString(string.Empty);
                    foreach (string key in formValues)
                    {
                        query[key] = this.Request.Form[key];
                    }

                    query["username"] = System.Web.Configuration.WebConfigurationManager.AppSettings["ApiUserName"];
                    query["password"] = System.Web.Configuration.WebConfigurationManager.AppSettings["ApiPassword"];

                    string apiurl = System.Web.Configuration.WebConfigurationManager.AppSettings["ApiURL"];

But in this was I will be exposing the username and password and these can be captured by users, so my question is how I can secure the API username and password?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You can encrypt the web.config with aspnet_regiis. This is to stop people with access to your server from reading sensitive information.

By the way, I would put your config settings inside a class, that can then be injected into your controllers – it will make unit testing easier.

Method 2

Generally, web.config is a secure file and IIS does not serve it, therefore it will not be exposed to users who are making requests to web server. Web server only serves specific type of files and web.config is surely not one of ’em.

Quite often you save your database connection string in it which includes password. Now imagine an scenario where web.config was not secure. You have created a major security threat to your application.

Therefore, specially as long as your project is not too big, you should not be worrying about it.

Yet, you may have a better approach but creating a project called “Resources” and save all the critical information such as settings, consts, enums and etc in there. That would be a slick and organized approach.

If you are passing the username/password over the wire though (for example in case of a secured API call), you may want to use https to make sure that information that are travelling are encrypted but that has nothing to do with the security of web.config file.

Method 3

The web.config file is just a file on the file system and so you should (mostly) consider its security in the same way as you would any other file. It will not be served by IIS (unless you make a frankly insane config change to IIS – easy to check for, just try and request it with a browser)

It is good practice to secure your website directory (c:/sites/my-site-here or whatever) using folder permissions to just the website app domain user to read the files (and the deployment user if needed) by using normal windows file permissions

So it may not be necessary to encrypt if you have confidence in the security of the web server. However if you are say on shared hosting, or selling the website code, or the source code is public, then it might be wise to encrypt it. it is a little bit hassle some though.

Method 4

Why use Web.config?

One of the advantages of having data in Web.config as opposed to storing it in Constants, Enums, etc… is that you can change the data for different environments easily.

Protecting data

The best way to secure the data in Web.config is to encrypt them. Instead of encrypting entire sections in the config file as suggested by Joe and user1089766 you can just encrypt the password string and store it in the config.

Retrieving data

You can use a helper function such as the one below to decrypt the keys.

private const readonly string decryptKey = "";
public string GetFromConfig(string key)
{
   var encryptedText = System.Web.Configuration.WebConfigurationManager.AppSettings[key];
   var plainText = Decrypt(encryptedText, decryptKey);
   return plainText;
}

In this way the decryption key will be inside the project common for all environments. But you can change the data in the web.config easily without recompiling your app.

PS: You can change the decryptionKey and the corresponding data with each version to improve security.

Method 5

I know this may sound like over engineering, but if you can, you really should use a secret management service, such as AWS Secrets Manager or Azure Key Vault.

By storing your passwords, even in encrypted form, in your web.config or app.config, you creating several problems for yourself:

  • now your encrypted passwords are going to be committed to your source control, making them accessible to anyone with the read access. To get rid of them properly, you’ll need to do a history rewrite (if you are using git) which is a major pain
  • while you technically can put your passwords in the machine-level config, and outside of the source control, you’ll need to update all those files when your password changes
  • anyone who’s got your encrypted password now can try to decrypt it, using either aspnet_regiis.exe tool (if that’s what you used to encrypt it), or if you rolled your own security, reverse engineer that using your source code, figuring out what decryption algo & key it is using
  • whenever you need to change a password, you’ll need to make changes to that file & re-deploy the application.

On the other hand, when you use a secret management service, no secrets or decryption key or algorithm is stored in your source code. Retrieving a secret is as simple as this:

For Azure Key Vault:

var keyVaultUrl = "https://<your-key-vault-name>.vault.azure.net/";
var credential =  new DefaultAzureCredential();    
var client = new SecretClient(vaultUri: new Uri(keyVaultUrl), credential);    
KeyVaultSecret secret = client.GetSecret("<your-secret-name>");    
Console.WriteLine($"{secret.Name}: {secret.Value}");

For AWS Secrets Manager (skipped some error handling code):

var client = new AmazonSecretsManagerClient(accessKeyId, secretAccessKey, 
                                            RegionEndpoint.APSoutheast2);
var request = new GetSecretValueRequest {
    SecretId = secretName
};
GetSecretValueResponse response = null;
response = client.GetSecretValueAsync(request).Result;

This approach has lots of advantages over storage of local secrets:

  • you don’t have to mess with storing different values in configs for Prod/Staging/Dev environments — just read appropriately named secrets (such as ‘[Dev|Prod|Stag]DBPassword`
  • only selected few people can have access to the very important secrects (such as, I dunno, say Transfer all $$$ from Deus account to all E-Coin wallets everywhere authorisation code)
  • if anyone steals your source code (disgruntled employee, accidental leak) non of your passwords have been leaked
  • changing a password is easy — you just update it using the could management console and restart the app(s)

I have written a couple of articles, showing how to set up and read secrets with AWS and Azure on my blog, feel free to check it out if you need step-by-step directions and complete source code:

Method 6

I have to encourage you to separate the code from the Keys. Even if you encrypt the file, someone can clone it from your repo and while it is encrypted, you may no longer be able to track the file, or may get access to a key in the future, etc.

Plus as Art indicated (and maybe others in the thread) this makes it is really easy to have a separate set of keys for Dev / Test / Prod / etc. If you encrypt the file, sounds like you are going to either have the same encrypted data and decryption key in all of these environments. You won’t necessarily have an easy way to change in one but not the others.

Think about the long game – not just passwords but other configuration information should be loaded and unique per environment (API Keys, etc.)

We use this approach for developers too. I don’t want each developer to have their own API key, passwords, etc so they don’t have access to systems they don’t need. I can shutdown a user’s API key if a development laptop is lost. I can rotate dev / test / prod API keys and only have to worry about changing in one place, not inform all users that a file has been updated and they need to re-clone.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x