Getting an A on Mozilla Observatory

Posted on May 5, 2017

So I’ve done this with a few sites so far and figured it may be worth a write up. It’s actually a lot less daunting than it seems. Here’s where you can test it.

jamie.ie, blog.jamie.ie and hoarding.me aren’t done yet as they’re hosted on WP Engine, a managed wordpress host so I haven’t gotten around to it (yet). Feel free to test on welp.me.

Assuming you’re already using nginx it’s just a case of adding a few lines to your default config. Lets start with the massive pain in the ass that is CSP. Kill me. I use a default that fails mozilla observatory, great start right? Don’t worry, we’ll pass everything else and get an A anyway so who cares. Most of these are necessary to run any sort of social site, facebook, google analytics, twitter etc. And the maxcdn bootstrap.

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://pagead2.googlesyndication.com https://connect.facebook.net/en_US/sdk.js https://platform.twitter.com https://www.google-analytics.com; img-src 'self' https://syndication.twitter.com https://www.facebook.com https://www.google-analytics.com data:; style-src 'self' 'unsafe-inline' https://maxcdn.bootstrapcdn.com https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com https://maxcdn.bootstrapcdn.com data:; frame-ancestors 'self'; frame-src 'self' https://staticxx.facebook.com https://www.facebook.com https://platform.twitter.com https://googleads.g.doubleclick.net; frame-ancestors 'self'; connect-src 'self' https://apis.google.com; object-src 'self' https://pagead2.googlesyndication.com";

The next three you shouldn’t be failing to begin with. CORS is the devil, so that’s skipped too. May god have mercy on your soul. Pinning keys is overkill, if you’re using Lets Encrypt it’s also a waste of time updating this every 3 months so don’t bother.

For HTTP Strict Transport Security;

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";

For Redirection;

server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://$host$request_uri;
server_name your-domain-name.tld;
}
server {
server_name your-domain-name.tld;
listen 443 ssl http2;
listen [::]:443 ssl http2;

You can omit both server_name directives if you’re only serving one site.

For Referrer Policy;

add_header Referrer-Policy "no-referrer";

For X-Content-Type-Options;

add_header X-Content-Type-Options nosniff;

For X-Frame-Options, it’s set in your CSP which we’ll added in the first part (frame-ancestors ‘self’)

For X-XSS-Protection;

add_header X-XSS-Protection "1; mode=block";

Harden your SSL settings with this;

ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SH$
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_session_tickets off;
ssl_ecdh_curve secp384r1;

Grab a beer and enjoy your A rating.