Security Headers seems to be one of the most skipped steps in just about every configuration out there. We have listed the minimum security headers which should be included in every instance of NGINX. Security Headers (Help prevent sniffing and manipulating our content by someone else) is a whole topic to itself on how to control the connection with clients. Not to mention, what we could possibly do to anyone using header manipulation to inject all sorts of fun. NGINX module and header manipulation is truly an art form that seemingly very few people understand. This is where the majority of the security work and tweaking comes into play in order to stay ahead of the curve. There are some lovely options for headers and how to use them.
We are using headers to deal with reporting and things like:
Header Syntax usage: add_header name value [always];
The below chart breaks down the top million requested websites - Scott Helme performed this very interesting study about the lack of Security Header use in the top million requested website's. The results for Februay 2019 came in. Whilst things didn't look too great in the first scan back in 2016, the rate of improvement being shown is incredible! These numbers are still a long way from where we'd like to see them but all of the metrics are showing considerable progress. Scott Helme Security Headers Test- securityheaders.io
nano /etc/nginx/sites-available/EXAMPLE_com_ssl.conf
server {
..............................
etag off;
proxy_cookie_path / "/; HTTPOnly:Secure";
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block; report=https://zombiesecured.report-uri.com/r/d/xss/enforce" always;
add_header Referrer-Policy no-referrer-when-downgrade always;
add_header Permissions-Policy geolocation=() always;
add_header NEL "{\"Report-To\":\"default\",\"max_age\":31536000,\"include_subdomains\":true}" always;
add_header Expect-CT enforce,max-age=30,report-uri="https://zombiesecured.report-uri.com/r/d/ct/enforce" always;
add_header X-Frame-Options DENY always;
add_header Cache-Control "public, max-age=31536000" always;
add_header MyHeader "Feel safe Zombie headers in use!!! It took %D microseconds to serve this request on Epoch Time %t microseconds" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Report-To "{\"group\":\"default\",\"max_age\":31536000,\"endpoints\":[{\"url\":\"https://zombiesecured.report-uri.com/a/d/g\"}],\"include_subdomains\":true}" always;
add_header Content-Security-Policy "script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; media-src 'self'; object-src 'self'; worker-src 'none'; frame-ancestors 'none'; form-action 'self'; report-uri https://zombiesecured.report-uri.com/r/d/csp/enforce; report-to default" always;
add_header X-Permitted-Cross-Domain-Policies none always;
}
systemctl restart nginx
Test results Febraury 2020 - Image courtesy of Securityheaders.io