.Net, IIS, Security, Sitecore, Web, XML

Encrypting .NET Config Files in a Shared Development Environment

This page will attempt to describe how to encrypt sensitive information contained in .NET config files using the RSA Key Container, as well as how to export/import the key from that container so that other developers may use the same key to work on the same project.

Helpful Tips: The aspnet_regiis.exe utility must be run as a administrator, otherwise you may receive “duplicate object” errors. In addition, you will want to run Visual Studio as an administrator to ensure the program has access to the RSA Key Container store.

Creating a Custom RSA Key Container

In this part we will create an RSA key container by using aspnet_regiis.exe with the -pc option. This identifies the RSA key container as a user-level key container. RSA key containers must be identified as either user-level (by using the -pku option) or machine-level (by not using the -pku option). For more information about machine-level and user-level RSA key containers, see Understanding Machine-Level and User-Level RSA Key Containers.

In this example the following command will create an RSA key container named SampleKeys that is a machine-level key container and is exportable:

cd \WINDOWS\Microsoft.Net\Framework\v4.0.*
aspnet_regiis -pc "SampleKeys"–exp

Adding your provider to the web.config

The following example shows the configProtectedData section of a Web.config file. The section specifies an RsaProtectedConfigurationProvider that uses a machine-level RSA key container named SampleKeys.

<configProtectedData>
   <providers>
    <add keyContainerName="SampleKeys" useMachineContainer="true" description="RsaCryptoServiceProvider" name="SampleKeys" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
   </providers>
</configProtectedData>

Importing and Exporting the Key Container

In order for another developer to run your project (encrypted by your key) you will need to  export a key to be used by another developer:

aspnet_regiis -px "SampleKeys" "C:\keys.xml" -pri

Once you pass this along to another user to use then import with the following command:

aspnet_regiis -pi "SampleKeys" "C:\keys.xml"

If this is a machine level container, the code should now run without the need to assign permissions. However, if it’s a user container (i.e. your app pool is ran by a specific user or service account), additional permissions may need to be assigned:

aspnet_regiis -pa "SampleKeys" "NT AUTHORITY\NETWORK SERVICE"
aspnet_regiis -pa "SampleKeys" "[impersonation account]"

To use the default RsaProtectedConfigurationProvider specified in the machine configuration, you must first grant the application’s Windows identity access to the machine key container named NetFrameworkConfigurationKey, which is the key container specified for the default provider. For example, the following command grants the NETWORK SERVICE account access to the RSA key container used by the default RsaProtectedConfigurationProvider:

aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT AUTHORITY\NETWORK SERVICE"

Encrypting and Decrypting Config Sections

.NET allows specific sections of a config file to be encrypted, so non-sensitive information can still be accessed. To encrypt a section:

aspnet_regiis -pef [section] [path] -prov [provider]

Where [section] is the name of the config section, relative to the configuration tag. [path] is the relative path to the directory containing the web.config file. For example, the following commands will encrypt the appSettings section as well as the impersonation credentials:

cd C:\SolutionFolder
aspnet_regiis -pef appSettings ProjectFolder -prov SampleKeys
aspnet_regiis -pef system.web/identity ProjectFolder -prov SampleKeys

To decrypt the appSettings section:

aspnet_regiis -pdf appSettings ProjectFolder

Partially Encrypting a Section

It may be necessary to only encrypt part of a section in a web.config file. For example, if the appSettings section contains multiple, non-sensitive keys and only a subset contain sensitive information. To encrypt only a few keys, a second appSettings section must be created and the new keys moved into it. The keys are accessed exactly the same way in the code, so no coding changes are needed.

First, register a new section name called secureAppSettings by placing the following XML under the configuration node:

<configSections>
<section name="secureAppSettings" type="System.Configuration.NameValueSectionHandler, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>

Next, create a new section called secureAppSettings and move the sensitive keys under it:

<secureAppSettings>
    <add key="Username" value="XXX" />
    <add key="Password" value="XXX" />
</secureAppSettings>
<appSettings>
    <add key="NotSensitive" value="XXX" />
</appSettings>

Finally, the new secure section can be encrypted and decrypted independently of the existing appSettings section:

aspnet_regiis -pef secureAppSettings ProjectFolder -prov ProviderName

App.config

This Microsoft utility was designed for web.config files. It will not find app.config files for other project types. To encrypt these config files, just rename them to web.config prior to encrypting, then rename back afterwards.

Other Helpful Links:

.Net, Troubleshooting, Visual Studio

How To Fix “no exports were found that match the constraint” In Visual Studio

So, you have that “no exports were found that match the constraint” message in Visual Studio, eh?

The first thing I would try doing on the affected version of visual studio is to go to programs and features, select the version and pick change: VSbugss3

When that loads let it repair. Once it does see if that resolves the issue.

VSbugss2

If it does not a more manual method that is to delete all of the contents of the ComponentModelCache folder from the following area (of which VS version is affected):

Put your username in the path:

VS 2012:

C:\Users\username\AppData\Local\Microsoft\VisualStudio\11.0\ComponentModelCache

VS 2013:

C:\Users\username\AppData\Local\Microsoft\VisualStudio\12.0\ComponentModelCache

VS 2015:

C:\Users\username\AppData\Local\Microsoft\VisualStudio\14.0\ComponentModelCache

It should look something like:

VSbugss1

If that fails there is also a patch that they released in response: https://www.microsoft.com/en-in/download/confirmation.aspx?id=36020#

Certificates, Web, Wordpress

Redirect All HTTP to HTTPS in WordPress with .htaccess

I recently had a request from a client to transfer all web traffic on some WordPress site (www or no www) to all be forced over HTTPS. And with all of the up and coming security issues that stem from HTTP-only traffic it is a must. Why you ask? Well, unless you are explicitly doing this already users may able to browse and intercept traffic from your site with no encryption. If you have a SSL certificate but have not done this to your WordPress site then please do so!

Edit your .htaccess file and append this somewhere at the bottom (and change your website URL to the URL that is associated with the SSL certificate):

RewriteCond %{HTTPS} !^on$
RewriteRule (.*) https://www.example.com/$1 [R,L]

After this you should see all browsing of HTTP to your site to be automatically redirected to HTTPS. Note: in some cases you will have to update all the links and content of your site to use links that are HTTPS also. There are useful plugins out there that can assist with doing a bulk conversion of this. Otherwise you users will not get the padlock icon on the page (or even cases where the page will not render entirely). Happy securing! Hope this helps, questions are always welcome.

HTML, JavaScript, Troubleshooting, Web

Check For Internet Explorer (IE) Compatibility Mode

Create a JavaScript file called iecheck.js and paste the following in the snippet:

function trueOrFalse() {
 return true;
}

function IeVersion() {
 // Set defaults
 var value = {
 IsIE: false,
 TrueVersion: 0,
 ActingVersion: 0,
 CompatibilityMode: false
 };

// Try to find the Trident version number
 var trident = navigator.userAgent.match(/Trident\/(\d+)/);
 if (trident) {
 value.IsIE = true;
 //Convert from the Trident version number to the IE version number
 value.TrueVersion = parseInt(trident[1], 10) + 4;
 }

// Try to find the MSIE number
 var msie = navigator.userAgent.match(/MSIE (\d+)/);
 if (msie) {
 value.IsIE = true;
 // Find the IE version number from the user agent string
 value.ActingVersion = parseInt(msie[1]);
 } else {
 // Must be IE 11 in "edge" mode
 value.ActingVersion = value.TrueVersion;
 }

// If we have both a Trident and MSIE version number, see if they're different
 if (value.IsIE &amp;&amp; value.TrueVersion &gt; 0 &amp;&amp; value.ActingVersion &gt; 0) {
 // In compatibility mode if the trident number doesn't match up with the MSIE number
 value.CompatibilityMode = value.TrueVersion != value.ActingVersion;
 }
 return value;
}

Once you have the JavaScript file then open your page where you are going to check for compatibility for and place a reference to the iecheck.js file in the head tag.

<script src="iecheck.js" type="text/javascript"></script>

After that you have multiple options on how to use the script.

For example, if you would like to check for compatibility and redirect then paste the following snippet inside of the body of your html:

<script type="text/javascript">
// 0 = not in compatibility view, 1 = in compatibility view
var ie = IeVersion();
if ((ie.CompatibilityMode == "0") && (ie.IsIE == "1")) {
window.location = "redirecttosomewhere.html"
}
else {
// do nothing, is in compatibility view
}
</script>

Another example would be if you just want to see the results on the page; just place this snippet inside of the body of your html:


<script type="text/javascript">
// <![CDATA[
var ie = IeVersion();
document.write("IsIE: " + ie.IsIE + "</br>");
document.write("TrueVersion: " + ie.TrueVersion + "</br>");
document.write("ActingVersion: " + ie.ActingVersion + "</br>");
document.write("CompatibilityMode: " + ie.CompatibilityMode + "</br>");
// ]]>
</script>

Hope this helps. Questions are always welcome.

Certificates, OpenSSL, Windows

Create .pem/.key/.crt Files from a .pfx Certificate Using OpenSSL on Windows

  1. First off, go and get OpenSSL:

Now that you are installed and ready to go you should now have a browsable file path to OpenSSL (i.e. C:\OpenSSL)

2. Obtain your PFX file and (for simplicity) place your PFX file in your OpenSSL directory.

(In this example we will assume we have a .pfx file called mycertificate.pfx and your OpenSSL directory is C:\OpenSSL)

3. Run this in command prompt (in your OpenSSL directory) to get the .pem file:

 
openssl pkcs12 -in mycertificate.pfx -out mypemfile.pem

You should now have a .pem file generated from your PFX file.

4. Run this in command prompt (in your OpenSSL directory) to extract the encrypted private key:

 
openssl pkcs12 -in mypemfile.pem -out myencryptedkey.key

You should now have the extracted encrypted private key out of the .pem file.

5. Run this in command prompt (in your OpenSSL directory) to create a decrypted private key from the encrypted version

 
openssl rsa -in myencryptedkey.key -out mydecryptedkey.key

You should now have the decrypted private key from your encrypted version.

6. Run this in command prompt (in your OpenSSL directory) to extract a .crt file from your PFX file:

 
openssl pkcs12 -in mycertificate.pfx -clcerts -nokeys -out certificate.crt

You should now an extracted .crt file from the PFX file.

That’s it! You should now have encrypted/decrypted keys as well as your .pem and .crt versions of your original PFX files. Happy certificating (I need to coin that term). Questions are always welcome.