Every couple of years, the Open Web Application Security Project (OWASP) publishes their top 10 security vulnerabilities of the day based on hacks & information that it has seen, every time security misconfiguration makes the list. Now if you consider the OWASP description, security misconfiguration means a lot. One often overlooked area is the proper way to secure the config files that applications use. Encrypting the files themselves may not be enough, let's have a look…
Problem
Consider a sample web config file, might have some setting in it that looks like this.
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" timeout="2880">
<credentials passwordFormat="Clear">
<user name="chris" password="FooBar" />
</credentials>
</forms>
</authentication>
Now there are problems no doubt with this config and settings, however for the time being, let's assume that this is what we have to work with and this is how users authenticate against our website, now this is just an authentication scheme, these credentials could be anything credentials to your database, email, ftp jobs…I am sure you get the picture. The difficulty is very easily with a small piece of malware I can read this config file relatively easily.
using (System.IO.StreamReader reader = new System.IO.StreamReader(PATH TO CONFIG))
{
while (!reader.EndOfStream)
{
String line = reader.ReadLine();
Console.WriteLine(line);
}
}
Now that we’ve understood the problem, consider the following solutions.
Encryption
Microsoft has provided a great tool for encrypting and decrypting application config files. It ships with the ASP.NET component of the .NET Framework and can be found in your Framework directory of .NET runtime. Disclaimer This tool only works for .NET 2.0 and greater. To encrypt my web config, I execute the following command.
C:\Windows\Microsoft.NET\Framework\v4.0.30319>aspnet_regiis.exe -pef "system.web
/authentication" PATH TO FILE
Microsoft (R) ASP.NET RegIIS version 4.0.30319.34209
Administration utility to install and uninstall ASP.NET on the local machine.
Copyright (C) Microsoft Corporation. All rights reserved.
Encrypting configuration section...
Succeeded!
Note: There are many ways to use this tool for encryption, those ways are outside the scope of this post.
As you can see the file is successfully encrypted and results in a config file that looks like:
<authentication configProtectionProvider="RsaProtectedConfigurationProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>Rsa Key</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>HgEGUWFJk1q4rX0xme1YA8s79jV7lnf0vAPRpoev1nLgxJtMXSYKhgydB2i35WOp
L0JOu3K238PU5u2irD8r1up2FU7nC6haN1wuC2MR3nTbJAijI0alvH28kuYUOgBMsQtKFp05wxwsBx9shE/
qzz8qM/adkQ8zzeOz/Ls4Wmc=</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>GoXJ4myf3ElKBIjSrJJqIQZjMxTwoO4ZE+HoX2kzISbgdP+p98X++O8vMrDe3PF0UlxI3nm
700pwheqzrApTNtRLBPeai51s7dIlu64rsyZl8bTgAhrhY3xsmwcWaWiCXanZcyFKVbcA7kp/Vo+VtrNfBIFxFgy/
ZI9KssaFzQAMJo1IQJwKsJeDIRSCM3gGLkXDr8Qavlz5Walh9KIXAxMal4KypQMs5wEl5M9chv5G62Oxo+kYkPdNe
RCsxdEBXjFnFEzZqWgPoqOkoK5yVj4v4qZsxlNOhAl9xCm9A1XRbg6IYYQCBn6TZ3xW3rZx2ayUu/NziX1FhMboOgZ+
/w==</CipherValue>
</CipherData>
</EncryptedData>
</authentication>
The file is now encrypted and how it got encrypted we really don’t care, and if we didn’t know any better, one could in theory think that their job was done, the config file is encrypted and we no longer have to worry about anything.
RE-Enter Malware Application
Very obviously, if I tried to read the config file in plain text as before when I get to the authentication section, the values are going to be encrypted and I am not going to read the values quite so easily. However, it’s not hard to tell that this config file has some encrypted sections in it and therefore I can modify my malware program as so.
VirtualDirectoryMapping vdm = new VirtualDirectoryMapping(@"PATH TO FILE", true
WebConfigurationFileMap wcfm = new WebConfigurationFileMap();
wcfm.VirtualDirectories.Add("/", vdm);
System.Configuration.Configuration cfg =
System.Web.Configuration.WebConfigurationManager.OpenMappedWebConfiguration(wcfm, "/");
ConfigurationSection cfgSect = cfg.GetSection("system.web/authentication");
if (cfgSect.SectionInformation.IsProtected)
{
cfgSect.SectionInformation.UnprotectSection();
}
cfg.Save();
But the awesome thing about executing this code prior to my file reading code is that, this code utilizes the same methods in the .NET framework to decrypt the config section if I can tell it which section is encrypted which I obviously can. Not only does this code decrypt the config file but it saves the file in a decrypted state back to the hard drive and the web application is none the wiser that anything has actually happened.
Protecting the Key Store
Just like the access controls to a particular file, key stores that are built into the framework can have access controls associated with them, So if I grant specific access to the keystore only certain users, perhaps the user that my application or webserver is running as, and nobody else then the server can decrypt the configuration file by everyone else will get an error. I can grant & revoke specific access to the key store via the following commands.
C:\Windows\Microsoft.NET\Framework\v4.0.30319>aspnet_regiis.exe
-pr "NetFrameworkConfigurationKey" "Domain\USERNAME"
Microsoft (R) ASP.NET RegIIS version 4.0.30319.34209
Administration utility to install and uninstall ASP.NET on the local machine.
Copyright (C) Microsoft Corporation. All rights reserved.
Removing ACL for access to the RSA Key container...
Succeeded!
The proceeding command revokes access to the NetFrameworkConfigurationKey
to a specified domain\user combination. If I wanted to grant access, the command is only slightly different.
C:\Windows\Microsoft.NET\Framework\v4.0.30319>aspnet_regiis.exe
-pa "NetFrameworkConfigurationKey" "Domain\USERNAME"
Now when my malware runs, I’ll get an exception that states the information could not be decrypted because I don’t have access to the RSA container. Therefore, I cannot access the keys required to decrypt the information. However if I am on the box, there is a good chance I might be able to figure out who the application is running as/under and I maybe able to do some impersonation, or get my application to run as said user and again I would have full access to be able to decrpyt the config file because my application would be running as the appropriate user.
Microsoft has already helped you out here by providing the APP Pool Identities, an application pool identity is essentially a dynamic identity that comes into play when the application services a request on your behalf. Therefore if all access to the RSA Key store by the application pool identity were removed, your config file would become even more secure, it’s more difficult to get services, or console apps to run as an app pool identity and where they do, there is some guessing that needs to happen. In order to add an application pool identity to the RSA container, the command is very similar to adding a user.
C:\Windows\Microsoft.NET\Framework\v4.0.30319>aspnet_regiis.exe
-pa "NetFrameworkConfigurationKey" "IIS APPPOOL\APP POOL NAME"
That’s great things are becoming even more secure.
Malicious Activity
Even though my Malware application can no longer read encrypted sections of the config file, I can still wreak havoc with your application by editing the config file. If I can’t steal information in the config file maybe I want to cause a DOS against your application. I might delete a whole encrypted section knowing there is sensitive information in there that you want to protect or I might write my own values into the file, if your config file stores the url of another application, I could potentially change it on you.
Protecting Against Malicious Activity
Just as you protect your RSA Key container using an ACL, you really need to protect your config file using a proper ACL. Once you’ve removed everyone from accessing the config file that doesn’t need access, just like with an application pool identity being added to the key container, you can add an application pool identity to the ACL of the config file. This will securely protect your file from unauthorized access and by adding the application pool identity you’re not going to break your web application.
Defense In Depth
Somebody once told me Once malware gets on the box its pretty much game over. I would tend to disagree with that statement, here a practical defense of securing config files has been carried out. The steps carried out were.
- Encrypting config file
- Securing the key container
- Securing config file
Often times, successful attacks are built step by step, where an attacker can open a config file and gain more sensitive information that allows them access to other resources on the network. Even if having someone on your box ruins your application, at least you’ve protected the network from further exposure and taken very good steps to contain the risk.