This post is authored by Victor Dzheyranov, a Senior Security Program Manager at Microsoft, who the IIS team has had the pleasure of working with on numerous occasions in the past. This post is long overdue, we should have posted this a while back. Better late than never.
A new capability that went sort of unnoticed with IIS 10.0 release was a change in data encryption providers used by default. Yet this is also a perfect example of how good security features should be: you never notice them while they work smoothly under the hood to protect you!
As we all know IIS and ASP.NET application use XML files to store configuration data. The XML schemas are compatible so you can often see IIS and ASP.NET configuration to coexist inside the very same file. (This is changing with ASP.NET Core though, a whole new story to be told next time). To protect data in the plain text configuration files data encryption providers are utilized to encrypt sensitive configuration parameters while at rest and to transparently decrypt them for an authorized entity (security principal) upon use. An application pool password is a good example of data you would like to keep encrypted and IIS does this for you using exact this mechanism starting with IIS 7.0.
In contrast to the earlier IIS versions, IIS 10.0 is set to use two new Cryptography API: Next Generation (CNG) providers by default: IISWASOnlyCngProvider and IISCngProvider. Out of the box, the IIS_IUSRS group only has access to the key associated with the IISCngProvider. However, application pool passwords are encrypted by WAS using the IISWASOnlyCngProvider and locked down to SYSTEM and Administrators only. Let’s have a closer look at this.
Whether configuration encryption is used for each attribute is determined by the attribute's definition in the schema of the containing configuration section. You can find that “password” attribute is set to be encrypted by default using IISWASOnlyCngProvider by looking into updated IIS_schema.xml file in the %WINDIR%\System32\inetsrv\config\schema directory.
To get an idea on what data encryption providers are available on your system have a look at applicationHost.config file in the file in the %WINDIR%\System32\inetsrv\config\ directory. Note “iisCngWasKey” key container name of the IISWASOnlyCngProvider provider.
CNG stores shared private keys in the %ALLUSERSPROFILE%\Application Data\Microsoft\Crypto\Keys\ directory. The container file names are hard to read, but you can get an idea of a container name by simply looking into the file opened in Notepad.
Check ACL settings on the file to verify that only SYSTEM and Administrators group have permission on it.
One caveat here is that if you are upgrading your server to Windows Server 2016 and IIS 10 using in-place upgrade approach, the upgraded IIS versions will use CNG for newly entered secrets only. If there's anything already encrypted, the upgrade will not decrypt and re-encrypt using new providers. For the application pool password example an admin would need to manually re-enter the password to start using CNG for that secret.
If you want to dive deeper into the topic, there is a list of links you can use as a starting point.
- IIS 7.0 Resource Kit Book, Chapter 13: “Managing Configuration and User Interface Extensions”, “Protecting Sensitive Configuration Data” and Chapter 14: “Implementing Security Strategies”, “Securing Sensitive Configurations”.
- CNG Key Storage and Retrieval
- Knowledge Base Article 977754
- Understanding Machine-Level and User-Level RSA Key Containers
- Encrypting Configuration Information Using Protected Configuration
- ASP.NET IIS Registration Tool (Aspnet_regiis.exe)