Remove unwanted response headers from IIS hosted site

You may receive an e-mail from your Security team after a scan, that your Web application exposing certain Response Headers that might get exploited by attackers to gain unauthorized access to the System.
While it may not always be necessary to mitigate these kind of vulnerabilities, you still have to weigh the options. This might be true even for say, a Reactjs app hosted on IIS.

If you do need to remove certain Response Headers like Server, X-AspNet-version and X-Powered-By, these can be taken care of at the IIS Server level or in web.config file.

We will firstly use the URL rewrite option which requires to be installed on IIS Server if not already present. You can download the installer here.

For the Server and X-Powered-By Response Headers, create Server variables as under URL Rewrite option as shown below:

Set the variable names as RESPONSE_SERVER and RESPONSE_X-POWERED-BY respectively.

Next create outbound rules using URL Re-write in IIS specifically for the Website. If you create these rules at the Server level, it’ll be applied to all Websites.

With Pre-condition set to None, make the below configuration using URL re-write in the Outbound rule. The same configuration requires to be done for RESPONSE_X-POWERED-BY server variable.

You can then test these Response Headers values should come as blank in the Dev Tools of your Browser.

For the X-AspNet-version Response Header, make the below entry in your Web.Config file. This will remove the Response Header altogether.

Add the following line in your web.config in the <system.Web> section:
<httpRuntime enableVersionHeader="false" />

Serve static json files on IIS hosted React App

When you have a React App hosted on IIS Server, you might need to access the static json files in your application for various purposes like json translations etc.

When you try to access these static files directly in browser or through code e.g. http://app/translation.json, you’ll get a 404 File Not Found error because the MIME type is not set by default in IIS. This is true for any other static file like woff files for fonts.

Under your Web.config file configuration section, place the below sample code within system.webServer tags.

<staticContent>
		<mimeMap fileExtension=".woff" mimeType="application/octet-stream" />
		<mimeMap fileExtension=".json" mimeType="application/json" />
	</staticContent>

The Web.config file is not available by default for a React App. You can either create one manually or make a change in the IIS Server Website configuration which will generate the Web.config file automatically and then you can add the above changes.

Encrypt web.config with RSA encryption

Encryption done locally on a Server using command line can be used only if the Application is hosted on the same machine. If the Application is hosted in a load-balanced environment, the encryption should be done in a way so that the private key can be imported on all the load-balanced machines.
The commands need to be run with Admin permissions on the machine.

Run the following commands in Command Prompt in the similar order with Admin permissions:

Traverse to the path as per .Net Framework-

cd C:\Windows\Microsoft.NET\Framework\v4.0.30319

Encrypting Config file without using RSA Provider

aspnet_regiis.exe -pef <section name>  <path to the config file>

-pef is the action to be performed for encryption.

e.g. aspnet_regiis.exe -pef “connectionStrings” “C:\Data\TestWebApp”

All the connection strings present in the above example will be encrypted.

Encrypting Config file using RSA Provider

Creating Key containers:

Aspnet_regiis.exe -pc “<name of Key container>” -exp

Asymmetric private keys should always be stored in a key container.

Add configProtectedData section in web.config to be encrypted:

<configProtectedData>
<providers>

<add name="MyRSAProvider"

type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=4.0.30319.0,

Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,processorArchitecture=MSIL"

keyContainerName="MyRSAKey"

useMachineContainer="true" />

</providers>

</configProtectedData>

The above section can only be added after < configSections > else it’ll be removed automatically.

The PublicKeyToken above can be found for the System.Configuration dll using the sn utility:

sn -T "C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Configuration.dll"

The key container name and the Provider name used above can be used in the example commands below.

Granting Access to an RSA Key Container to the AppPool:

aspnet_regiis -pa “<name of Key container>” “NT AUTHORITY\NETWORK SERVICE” -full

Encrypt command using Provider:

aspnet_regiis.exe -pef <name of config section> <path to the Config file> -prov “<name of Provider>”

Exporting the Key Container in Order to be used on Other Machines:

aspnet_regiis -px “< name of Key container >” <Path for Keys XML file> -pri

Import Key Container on another machine:

aspnet_regiis -pi “< name of Key container>” <Path for Keys XML file>

Path for keys e.g. C:\rsakeys.xml. The xml file can be copied to the same path on the other machine.

Delete the Xml File from Your Server

ASP.Net will automatically decrypt the Connection String using the grant permission given above to the AppPool and hence you need to access the Connection String in the same way as you would do normally.

To decrypt the config section locally using aspnet_regiis.exe use the below command:

Decrypt command: aspnet_regiis.exe -pdf < name of config section> <Path to the Config file>

e.g. aspnet_regiis.exe -pdf “connectionStrings” “C:\Data\TestWebApp”

Create Virtual directory in Visual Studio 2017 IIS Express

You may be facing a scenario where the Images folder of your Project is hosted in another directory on your machine e.g. C:\Data\Images and not under the Project directory structure. In this case, if you need to check whether the Images are loading correctly, you’ll need to create a Virtual directory in your Web application/MVC/WebAPI Project.

Follow the below steps:

1. Right-click on your Project properties and go to the Web tab and provide the URL for the required Virtual directory and click on the button Create Virtual directory. This option edits the ApplicationHost.config file.

2. Run the application and right-click on the IIS Express icon in the status-bar notification tray. Select your website and open the config file.

3. Look for the site tag and find your website and you’ll find the Virtual directory nested tag. Edit the path and physicalPath attribute to the folder on your machine as shown below:

<site name="MyApi" id="2">                 
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="C:\MyApi" />                 
</application>                 
<application path="/uploads" applicationPool="Clr4IntegratedAppPool">                     
<virtualDirectory path="/" physicalPath="C:\Data\Images\uploads" />                 
</application>                 
<bindings>                     
<binding protocol="http" bindingInformation="*:62216:localhost" />                 
</bindings>             
</site>

After making these changes, refresh the app to view the images in your app via localhost.

To know how to create a Virtual Directory in IIS for a website, check this post.

Show some love for the pit in my PayPal account.

Take care of your health. Click here to know more.

Enable PUT and DELETE Http verbs for WebAPI with Cors on IIS 8.5

WebAPI in .Net by default allows only the GET, POST, OPTIONS and HEAD verbs. To allow PUT and DELETE, you need to remove the WebDAV handler and module from the request pipeline by making the following changes to the Web.Config.

The WebDAV element contains the settings that configure Web Distributed Authoring and Versioning (WebDAV) for Internet Information Services (IIS) 7 or above. WebDAV is an Internet-based open standard that enables editing Web sites over HTTP and HTTPS connections. You may get a 405 error code due to WebDAV.

<system.webServer>
    <handlers>
      <remove name="WebDAV" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <validation validateIntegratedModeConfiguration="false" />
    <modules>
      <remove name="WebDAVModule" />
    </modules>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="http://somedomain" />
        <add name="Access-Control-Expose-Headers" value="Content-Type, Accept, expiry, uid, access-token, token-type" />
        <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>

Also, the ExtensionlessUrlHandler-Integrated-4.0 handler needs to allow all verbs with a * or a manual entry for specific verbs. The minimum runtime requirement is 4.0 to make this work.

The last bit to check for a message that says e.g. PUT /Rejected-By-UrlScan . Check the logs under C:\Windows\System32\inetsrv\urlscan\Logs on the Server. You may need to edit the config file to allow those verbs or remove the UrlScan 3.1 service in the ISAPI tab of your Service in IIS which points to urlscan.dll. This is usually mentioned last in the list.

CustomHeaders are part of enabling Cors. Please note that Access-Control-Allow-Origin should not allow “*” . It should mentions specific domain that requires to be allowed for Cors. You can expose custom headers using Access-Control-Expose-Headers and allow specific methods using Access-Control-Allow-Methods.

Show some love for the pit in my PayPal account.