Secure your web site/application with a simple package.
Install NuGet Package Acme.Web.Security.Headers from Package Manager or from Package Manager Console:
PM> Install-Package Acme.Web.Security.Headers
After installation your web.config has a new configuration section with those default values:
<configuration>
<acme.web.security.headers xmlns="Acme.Web.Security.Headers" referrerPolicy="StrictOriginWhenCrossOrigin" frameOptions="Deny">
<contentSecurityPolicy insecureRequests="UpgradeInsecureRequests">
<default none="true" />
<script self="true" />
<connect self="true" />
<img self="true" />
<style self="true" />
<base self="true" />
<form self="true" />
<frameAncestors none="true" />
</contentSecurityPolicy>
<strictTransportSecurity maxAge="31536000" includeSubDomains="true" preload="true"/>
</acme.web.security.headers>
</configuration>
The section has a schema to let you have all intellisense and documentation for every property and for every possible values.
The package set your cookies to secure by default (Require SSL & HTTP Only)
<configuration>
<system.web>
<httpCookies requireSSL="true" httpOnlyCookies="true" />
</system.web>
</configuration>
If your web site has to work in HTTP you may adapt that configuration but I strongly suggest you to switch and consider free alternatives like Let’s Encrypt. If you need some cookies in client side then you should set HttpCookie.HttpOnly=false in your code.
The package remove all sensitive information like Server Name, Powered By, ASP.NET & MVC Versions (this configuration is also enforced by code)
<configuration>
<system.web>
<httpRuntime enableVersionHeader="false" enableHeaderChecking="true" />
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Server" />
<remove name="X-Powered-By" />
<remove name="X-AspNet-Version" />
<remove name="X-AspNetMvc-Version" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Inspired by "Shhh… don’t let your response headers talk too loudly" by Troy Hunt
It removes the trace handler (trace.axd) completly. To avoid "/trace.axd" returning a 500 if not enabled and telling the world you are running an ASP.NET website!
<configuration>
<system.webServer>
<handlers>
<remove name="TraceHandler-Integrated" />
<remove name="TraceHandler-Integrated-4.0" />
</handlers>
</system.webServer>
</configuration>
Inspired by "Securing the ASP.NET MVC Web.config" by Muhammad Rehan Saeed
It adds SameSite support (in LAX by default)
<configuration>
<system.webServer>
<rewrite>
<outboundRules>
<rule name="Add SameSite" preCondition="No SameSite">
<match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
<action type="Rewrite" value="{R:0}; SameSite=lax" />
<conditions>
</conditions>
</rule>
<preConditions>
<preCondition name="No SameSite">
<add input="{RESPONSE_Set_Cookie}" pattern="." />
<add input="{RESPONSE_Set_Cookie}" pattern="OpenIdConnect\.nonce\..+" negate="true" />
<add input="{RESPONSE_Set_Cookie}" pattern="; SameSite=lax" negate="true" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
Inspired by "Adding SameSite Cookie Support In ASP.NET" by Kamran Ayub and "Cross-Site Request Forgery is dead!" by Scott Helme
If you use this package with Umbraco you may add this section to your web.config:
<configuration>
<location path="umbraco">
<acme.web.security.headers xmlns="Acme.Web.Security.Headers" frameOptions="SameOrigin">
<contentSecurityPolicy>
<script self="true" unsafeInline="true" unsafeEval="true" />
<style self="true" unsafeInline="true" />
<img self="true" data="true">
<add host="umbraco.tv" />
<add host="dashboard.umbraco.org" />
</img>
<media>
<add host="player.vimeo.com" />
<add host="*.vimeocdn.com" />
</media>
<frameAncestors self="true" />
</contentSecurityPolicy>
</acme.web.security.headers>
</location>
</configuration>
1.0.2:
- Adds base-uri directive
- Adds block-all-mixed-content directive
- Adds upgrade-insecure-requests directive
- Adapt the default configuration based on content-security-policy.com
- Adds recomandations from OBSERVATORY by mozilla
- Deny by default, using default-src 'none'
- Clickjacking protection, using frame-ancestors
- Restricts use of the tag by using base-uri 'none', base-uri 'self', or specific origins
- Restricts where contents may be submitted by using form-action 'none', form-action 'self', or specific URIs
- Unit tests
- Dotnet Core support
- Change some specific cookie names related to ASP.NET like ASP.NET_SessionId, Anti-Forgery Tokens
To avoid reinventing the wheel and making mistakes, all header documentation is extracted from The MDN Web Docs:
"X-Content-Type-Options" by DBaron, fscholz, WhatIsHeDoing, teoli is licensed under CC-BY-SA 2.5.
"Referrer-Policy" by Ginkoid, dhausknecht, twm, ptamarit, fscholz, chrisdavidmills, lfaraone, pox is licensed under CC-BY-SA 2.5.
"Strict-Transport-Security" by simplenotezy, plygrnd, fscholz, hmft, gregoryh, AxelF, koluke, jwhitlock, Sebastianz, Tom_D, pijaykrause, jswisher, fowl2, coffeina, wbamberg, dbaxa, Annevk, konklone, teoli, AD7six, Sheppy, wayno, mkato, tregagnon, st3fan, yyss, paul.irish, [email protected], CesarB, sidstamm is licensed under CC-BY-SA 2.5.
"X-XSS-Protection" by ccsplit, Slaweally, arthurwhite, fscholz is licensed under CC-BY-SA 2.5.
"X-Frame-Options" by jpmedley, Jas0n99, shellac_, comfytoday, fscholz, SphinxKnight, Benedito1, kishore333, teoli, JesseNaranjo, Sebastianz, freddyb, Sheppy, foxbrush, Hsvnsson, Starefossen, Ellani cola, Daniel Veditz, anthonyryan1, estelle, caioproiete, kscarfone, rothshahar, gasubic, maybe, rockad, mnoorenberghe, localhorst, yyss, Psz is licensed under CC-BY-SA 2.5.
"Content Security Policy (CSP)" by vipsh18, PeterDavidCarter, fscholz, David-5-1, allstars.chh, jpmedley, coolaj86, hooch, partizanos, teoli, chrisdavidmills, blackoutjack, Sheppy, davidbgk, imelven, dregad, abarth, devdatta, mathjazz, Marsf, mnoorenberghe, jswisher, bsterne, fryn is licensed under CC-BY-SA 2.5.
"CSP: block-all-mixed-content" by fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: upgrade-insecure-requests" by fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: base-uri" by nhoizey, fscholz is licensed under CC-BY-SA 2.5.
"CSP: child-src" by sideshowbarker, fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: connect-src" by fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: default-src" by jpmedley, fscholz, stuajc, teoli, sergiferran is licensed under CC-BY-SA 2.5.
"CSP: font-src" by fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: form-action" by fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: frame-src" by twm, fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: frame-ancestors" by JasonTarka, fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: img-src" by fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: manifest-src" by fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: media-src" by fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: object-src" by fscholz is licensed under CC-BY-SA 2.5.
"CSP: script-src" by thinktt, vic511, Braiam, jpmedley, fscholz, DaleGardner, teoli is licensed under CC-BY-SA 2.5.
"CSP: style-src" by fscholz is licensed under CC-BY-SA 2.5.
"CSP: worker-src" by yvanavermaet, chrisdavidmills, fscholz, teoli is licensed under CC-BY-SA 2.5.
"CSP: require-sri-for" by Sheppy, fscholz, phillycheeze, freddyb is licensed under CC-BY-SA 2.5.
If I’ve forgot to mention you, send me pull request with the correct attribution and I will update it ASAP ;-)