Secure Web Application via Web.config File in ASP.NET MVC

Introduction 

 
Almost a year back, one of my clients performed a VAPT test for a web app that I made. VAPT stands for "Vulnerability Assessment and Penetration Testing", there are two parts to it, firstly "Vulnerability Assessment Test" is used to discover vulnerabilities in the current code that can be used to exploited to cause damage and differ them from that cannot, secondly "Penetration Test" attempt to exploit the vulnerabilities in a system to determine whether unauthorized access or other malicious activity is possible and identify which flaws pose a threat to the application. Together, penetration testing and vulnerability assessment tools provide a detailed picture of the flaws that exist in an application and the risks associated with those flaws.
 
After the tests, I received a list of recommendations that I had to impart to make the web application more secure. In this article, I have listed all the changes I did only in the web config which has helped me make the site secure.
 

Server Remote Version Disclosure

 
Generally, a web server normally shows some valuable pieces of information about the server like the type of server, the version number, and the operating system. This information is available in the header of the HTTP response. Below is the default response from the IIS which contains the version of the IIS on the server, the version of the ASP.NET, and the version of the MVC.
 
Secure Web Application Via Web.config File In ASP.NET MVC
 
To Remove "X-Powered-By" and "X-AspNetMvc-Version" we can use the customHeaders tag which is an element of httpProtocol.
  1. <system.webServer>    
  2.    <httpProtocol>    
  3.      <customHeaders>    
  4.        <remove name="X-Powered-By" />    
  5.        <remove name="X-AspNetMvc-Version" />    
  6.      </customHeaders>    
  7.    </httpProtocol>    
  8. </system.webServer>    
The "X-AspNet-Version" and "Server" are not a part of the Custom Headers and cannot be removed using a remove tag inside the customHeaders.
 
To remove "X-AspNet-Version" we can set the attribute enableVersionHeader to false in the httpRuntime tag like in the snippet given below:
  1. <system.web>    
  2.     <httpRuntime targetFramework="4.6" enableVersionHeader="false" />    
  3. </system.web>   
To remove "Server" from the response headers we might just need to make some changes in the global.asax. In the below snippet I have used the PreSendRequestHeaders Event. The significance of this event is that it occurs before ASP.NET send HTTP headers to the client. So all we need to do is to remove the "Server" from the headers in this event.
  1. protected void Application_PreSendRequestHeaders()    
  2. {    
  3.       if (HttpContext.Current != null)    
  4.       {    
  5.          HttpContext.Current.Response.Headers.Remove("Server");    
  6.       }    
  7. }    

Clickjacking Vulnerability

 
Clickjacking is a client-side vulnerability and occurs mainly when the attacker is able to frame the website content mostly forms and put some transparent layer over the page in order to trick the user to click on buttons that are not intended by the victim. For example: If there is a delete profile button on the page, the attacker could easily frame the page and put a transparent layer over the page saying win lottery, the victim will click on the button with the intention of winning the lottery but he/she will lose his account.
 
To overcome this problem, we need to add "X-Frame-Options" in the header of the HTTP Request. This will prevent the browsers from framing the site outside the origin.
  1. <system.webServer>    
  2.   <httpProtocol>    
  3.     <customHeaders>    
  4.       <add name="X-Frame-Options" value="DENY" />    
  5.     </customHeaders>    
  6.   </httpProtocol>    
  7. </system.webServer>    

Cross-Site Scripting Attacks

 
Cross-site scripting, also known as XSS, is basically a way to inject code that will perform actions in the user’s browser on behalf of a website. Sometimes, this is seen by the user and sometimes it can go totally unnoticed in the background.
 
This can be prevented by adding the "X-Xss-Protection" to the HTTP header with the value "1; mode=block" this enables the XSS filtering that is enabled by default in the browser. If a cross-site scripting attack is detected, the browser will sanitize the page (remove the unsafe line i.e inline javascript).
  1. <system.webServer>    
  2.   <httpProtocol>    
  3.     <customHeaders>    
  4.       <add name="X-Xss-Protection" value="1; mode=block" />    
  5.     </customHeaders>    
  6.   </httpProtocol>    
  7. </system.webServer>    

Content sniffing

 
Content sniffing, also known as media type sniffing or MIME sniffing, is the practice of inspecting the content of a byte stream to attempt to deduce the file format of the data within it.
 
This can be prevented by adding the "X-Content-Type-Options" to the HTTP header with the value "nosniff". This tells the browser that the MIME types advertised in the Content-Type headers should not be changed and be followed, in turn preventing the browser from sniffing (i.e guessing the MIME type).
  1. <system.webServer>    
  2.   <httpProtocol>    
  3.     <customHeaders>    
  4.       <add name="X-Content-Type-Options" value="nosniff" />    
  5.     </customHeaders>    
  6.   </httpProtocol>    
  7. </system.webServer>    

Set Referer to Origin

 
The Referer header contains the address of the previous web page from which a link to the currently requested page has been invoked. This is what Google Analytics uses to identify the inbound traffics to your site. Referer's is not a potential security threat, but sometimes may in revealing some sensitive data or paths of some sensitive resources in the web application. So to prevent that, we need to add the "Referrer-Policy" to the HTTP header with value "origin". Now the browser will always set the referrer header to the origin from which the request was made. This will strip any path information from the referrer's information.
  1. <system.webServer>    
  2.   <httpProtocol>    
  3.     <customHeaders>    
  4.       <add name="Referrer-Policy" value="origin" />    
  5.     </customHeaders>    
  6.   </httpProtocol>    
  7. </system.webServer>    

Prevent Cross-Domain Calls

 
This is not a potential security threat, but again is revealing some sensitive data that's available on one domain and is shown in another. The "X-Permitted-Cross-Domain-Policies" header tells the browser what cross-domain policies they can use. In order to prevent the loading of data from your domain, we need to set the header’s value to "none".
  1. <system.webServer>    
  2.   <httpProtocol>    
  3.     <customHeaders>    
  4.       <add name="X-Permitted-Cross-Domain-Policies" value="none" />    
  5.     </customHeaders>    
  6.   </httpProtocol>    
  7. </system.webServer>    

Enable HTTP Strict Transport Security (HSTS)

 
HTTP Strict Transport Security is relatively new and is recently introduced in IIS 10.0. This allows a web application to declare itself as a secure host and to inform browsers that it should be contacted only through HTTPS connections. HSTS is an opt-in security enhancement that enforces HTTPS and significantly reduces the ability of man-in-the-middle type attacks to intercept requests and responses between servers and clients. This can be done by adding the "Strict-Transport-Security" header with value "max-age=31536000; includeSubDomains" which I presume is self-explanatory.
  1. <system.webServer>    
  2.   <httpProtocol>    
  3.     <customHeaders>    
  4.       <add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains" />    
  5.     </customHeaders>    
  6.   </httpProtocol>    
  7. </system.webServer>    

Prevent Cookie Poisoning

 
Cookie Poisoning is an act of modifying the contents of the cookie from the client and make the web application behave differently. Actually, I mostly used it as a feature but after the test (VAPT test) I changed my mind. To prevent the browser from modifying the contents of the cookies, we add a tag httpCookies in which we need to set the attribute httpOnlyCookies to true.
  1. <system.web>    
  2.    <httpCookies httpOnlyCookies="true" requireSSL="false" />    
  3. </system.web>    
The httpOnlyCookies flag tells the browser that the cookie should only be accessed to be sent to the server with a request, not by client-side scripts like JavaScript. This attribute helps protect the cookie from being stolen through cross-site scripting flaws.
 

Prevent HTTP Header Injection

 
The HTTP header injection is an attack where an attacker can use a custom-header to insert an untrusted data in the response header. the attacker can use it to manipulate the headers, in turn, allowing the site to redirect the user to a different page, perform cross-site scripting attacks, or even rewrite the page. There is a way to prevent this, by encoding the carriage return and newline characters, \r and \n, that are found in response headers helping to avoid injection attacks that echo untrusted data contained in the header.
 
Please check the link for a detailed explanation of how HTTP Header injection work, in case you didn't find my one-liners helpful.
 
Note Because there is a performance impact from looking at headers, if you are certain you are already doing the right checks, turning off this feature can improve the performance of your application.
 
So to enable HeaderChecking, we can set the attribute enableHeaderChecking to true in the httpRuntime tag like in the snippet given below.
  1. <system.web>    
  2.   <httpRuntime targetFramework="4.6" enableHeaderChecking="true" />    
  3. </system.web>    
Resources and References:
  1. Wikipedia
  2. Veracode
  3. SecurityBrigade
  4. jardinesoftware.net
  5. Code-Spirit.com