Adding security headers to prevent XSS and MiTM attacks in .Net Core
As a developer, we need to consider security when designing and building web applications. HTTP Response Headers allow server to pass additional information to instruct browsers how to handle sensitive data and content of the application and/or from external or untrusted sources. HTTP response security headers provide an extra layer of protection to help mitigating vulnerabilities and attacks.
One way to add those security headers from .Net Core application is by writing a custom action filter that would be executed before serving any response from the application.
Below is a example of the custom attribute:
To apply this globally for all responses, we can add this to the Startup class as in below:
To apply trusted source for any particular action:
And here is the outcome:
HAPPY CODING 👌
One way to add those security headers from .Net Core application is by writing a custom action filter that would be executed before serving any response from the application.
Below is a example of the custom attribute:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SecurityHeadersAttribute : ActionFilterAttribute | |
{ | |
private readonly string transport_security_policy = "Strict-Transport-Security: max-age=31536000; includeSubDomains"; | |
private readonly string content_type_policy = "nosniff"; | |
private readonly string frame_policy = "sameorigin"; | |
private readonly string referrer_policy = "no-referrer"; | |
private readonly string xss_protection_policy = "X-XSS-Protection: 1; mode=block"; | |
private readonly string content_security_policy = "default-src 'self' {0}; object-src 'none'; frame-ancestors 'none'; base-uri 'self';"; | |
private readonly string _sources; | |
public SecurityHeadersAttribute(params string[] trustedSources) | |
{ | |
_sources = trustedSources?.Join(" "); | |
} | |
public override void OnResultExecuting(ResultExecutingContext context) | |
{ | |
var result = context.Result; | |
if (result is ViewResult) | |
{ | |
//https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security | |
AddResponseHeader(context, "Strict-Transport-Security", transport_security_policy); | |
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options | |
AddResponseHeader(context, "X-Content-Type-Options", content_type_policy); | |
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options | |
AddResponseHeader(context, "X-Frame-Options", frame_policy); | |
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy | |
AddResponseHeader(context, "Referrer-Policy", referrer_policy); | |
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy | |
var csp = string.Format(content_security_policy, _sources); | |
AddResponseHeader(context, "Content-Security-Policy", csp); // For standards compliant browsers | |
AddResponseHeader(context, "X-Content-Security-Policy", csp); // For IE | |
//https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection | |
AddResponseHeader(context, "X-XSS-Protection", xss_protection_policy); | |
} | |
} | |
/// <summary> | |
/// Appends a header to current response with specified value | |
/// </summary> | |
/// <param name="context"></param> | |
/// <param name="key"></param> | |
/// <param name="value"></param> | |
private void AddResponseHeader(ResultExecutingContext context, string key, string value) | |
{ | |
if (!context.HttpContext.Response.Headers.ContainsKey(key)) | |
{ | |
context.HttpContext.Response.Headers.Add(key, value); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void ConfigureServices(IServiceCollection services) | |
{ | |
// configure app services here... | |
// add security header as global filter | |
services.AddMvc(config => config.Filters.Add(new SecurityHeadersAttribute())); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[HttpGet] | |
[SecurityHeaders("https://www.google.com/recaptcha/","https://www.gstatic.com/recaptcha/")] | |
public async Task<IActionResult> Login(string returnUrl) | |
{ | |
var loginViewModel = await _account.BuildLoginViewModelAsync(returnUrl); | |
return View(loginViewModel); | |
} |
And here is the outcome:
HAPPY CODING 👌
security headers
ReplyDelete