A big shoutout goes to Troy Hunt and Leo Laporte and Steve Gibson from https://www.grc.com/securitynow for sharing their security knowledge.
Pre-Requisite: SSL Certificate
I have mentioned before how to obtain an A+ rating on your SSL certificate with the help of https://ssllabs.com/ssltest before in my Digital Ocean and AWS and Vultr Ubuntu server (NGINX, NodeJS etc) setup guides. Also an SSL certificate can be free and installed in 1 minute.
I will assume you have an SSL Labs A+ server rating on your site and you want to secure your site some more. You will need to secure your site some more by enabling content headers for Content Security Policy and Public Key Pinning.
Why
Read this article from Troy Hunt that explains why CSP is important: The JavaScript Supply Chain Paradox: SRI, CSP and Trust in Third Party Libraries
HTTP Public Key Pinning
Full credit goes to this site for explaining how to setup HTTP Public Key Pin and (add a NGINX header to reference two new keys that we link to the main certificate). Basically, we need to generate two new certificates on our server (linked to our master certificate from our CA) and deliver the hashes to the client as a header.
openssl x509 -pubkey < chained.crt | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
> Base64Output01Removed###########################=
openssl genrsa -out chained.first.pin.key 4096
> Generating RSA private key, 4096 bit long modulus
> …
openssl req -new -key yourserver.first.pin.key -sha256 -out yourserver.first.pin.csr
> Country Name (2 letter code) [AU]:
> State or Province Name (full name) [Some-State]:
> Locality Name (eg, city) []:
> Organization Name (eg, company) [Internet Widgits Pty Ltd]:
> Organizational Unit Name (eg, section) []:
> Common Name (e.g. server FQDN or YOUR name) []:
> Email Address []:
> Please enter the following ‘extra’ attributes
> to be sent with your certificate request
> A challenge password []:
> An optional company name []:
openssl req -pubkey < yourserver.first.pin.csr | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
> Base64Output02###########################=
openssl genrsa -out chained.second.pin.key 4096
> Generating RSA private key, 4096 bit long modulus
> …
openssl req -new -key yourserver.second.pin.key -sha256 -out yourserver.second.pin.csr
> Country Name (2 letter code) [AU]:
> State or Province Name (full name) [Some-State]:
> Locality Name (eg, city) []:
> Organization Name (eg, company) [Internet Widgits Pty Ltd]:
> Organizational Unit Name (eg, section) []:
> Common Name (e.g. server FQDN or YOUR name) []:
> Email Address []:
> Please enter the following ‘extra’ attributes
> to be sent with your certificate request
> A challenge password []:
> An optional company name []:
openssl req -pubkey < yourserver.second.pin.csr | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
> Base64Output03###########################=
# Add the following to the NGINX default configuration
server {
…
add_header Public-Key-Pins ‘pin-sha256=”Base64Output01###########################=”; pin-sha256=”Base64Output02###########################=”; pin-sha256=”Base64Output03###########################=”; max-age=2592000; includeSubDomains’;
…
}
nginx -t
nginx -s reload
/etc/init.d/nginx restart
This should solve the pinning ratings. I can check with https://securityheaders.io
Content Security Policy
Content Security Policy helps prevent cross-site scripting (XSS), clickjacking and other code injection attacks on your site by allowing your site to pre-define where resources can load from. Content Security Policy is supported in modern web browsers only. Here is a good explanation of CSP and a hackers cheat sheet for how to XSS Inject a site.
You can use this site to review your websites (or your bank’s website security): https://securityheaders.io/
I decided to check a big bank’s CSP/XSS configuration.
St George Bank appears to be missing a number of potential security configurations (above). I ran the checker over a site I was building and I got a missing Content Security Polity warning also.
If your site just delivers text (no images or media) and does not use Google Analytics or content from remote CDN’s then defining a Content Security Policy is easy in NGINX.
But chances are you will need to generate a detailed CSP to allow Google Analytics, Font’s and scripts to load/run.
There are loads of sites that will help you generate you a CSP ( here, here etc) but it is best to add the configuration above to your NGINX config then load your website google chrome and look for any CSP errors and then add them into the CSP generator, export to NGINX, save and recheck in google chrome until all issues are solved.
A recent version of Google Chrome will give you a good indication of what resources it blocked (that were not covered in your Content Security Policy).
I suggest you go to https://report-uri.io/home/generate and for each failing resource resolve that issue by defining the allowed resources in your policy.
After about 20 reloads of my CSP at https://report-uri.io/home/generate on my site and CSP validation with https://cspvalidator.org/ I have a working minimum Content Security Policy allowing resources on my site (real names redacted, note my CDN server that I use for misc resources).
My Final Content Security Policy.
script-src 'self' 'unsafe-inline' https://myservername.com:* https://myservername-cdn:* https://*.google-analytics.com https://*.google.com; style-src 'self' 'unsafe-inline' https://myservername.com:* https://fonts.googleapis.com:*; img-src 'self' https://myservername.com:* https://*.google-analytics.com https://*.google.com; font-src 'self' data: https://myservername.com:* https://myservername-cdn:* https://fonts.googleapis.com:* https://fonts.gstatic.com:*; connect-src 'self' https://myservername.com:* https://myservername-cdn:* https://*.google-analytics.com https://*.google.com; media-src 'self' https://myservername.com:* https://myservername-cdn:* https://*.google-analytics.com https://*.google.com; child-src 'self' https://player.vimeo.com https://www.youtube.com; form-action 'self' https://myservername.com:* https://myservername-cdn:*;
Spaced out to see what is set.
script-src 'self' 'unsafe-inline' https://myservername.com:* https://myservername-cdn:* https://*.google-analytics.com https://*.google.com; style-src 'self' 'unsafe-inline' https://myservername.com:* https://fonts.googleapis.com:*; img-src 'self' https://myservername.com:* https://*.google-analytics.com https://*.google.com; font-src 'self' data: https://myservername.com:* https://myservername-cdn:* https://fonts.googleapis.com:* https://fonts.gstatic.com:*; connect-src 'self' https://myservername.com:* https://myservername-cdn:* https://*.google-analytics.com https://*.google.com; media-src 'self' https://myservername.com:* https://myservername-cdn:* https://*.google-analytics.com https://*.google.com; child-src 'self' https://player.vimeo.com https://www.youtube.com; form-action 'self' https://myservername.com:* https://myservername-cdn:*;
Here is what I added to my NGINX configuration (but with my real servers names)
Misc SSL Certificate Issues
https://www.ssllabs.com/ssltest is the go-to site for checking your sites SSL certificate for issues.
Basic Server testing with asafaweb.com
https://asafaweb.com/ is a great site that tests your server to common security issues. Click on the orange or red buttons for an explanation and resolution.
Testing with SecurityHeaders.io
If everything is configured you will get all green.
CVE Exploits Database
After your server is secure you cannot sit back and pat yourself on the back, vulnerabilities can appear overnight and it is up to you to patch and update your server, services and software.
- NGINX from time to time has vulnerabilities that need urgent patching.
- OpenSSL needs checking for vulnerabilities from time to time. A bug was found in June this year that required urgent patching (blog post here).
- Spectre and Meltdown bug
Your Code
Once you have a secure web server, SSL, XSS pinning and other security configuration setup you will need to ensure any code you develop is secure too.
Read the Open Web Application Security Project’s Top 10 Developer Security considerations.
Security
As a precaution, do check your website often in https://www.shodan.io and see if it has open software or is known to hackers.
Keep Yourself Informed
Follow as many security researchers as you can on Twitter and keep up to date. (e.g 0xDUDE)
Check out the extensive Hardening a Linux Server guide at thecloud.org.uk: https://thecloud.org.uk/wiki/index.php?title=Hardening_a_Linux_Server
Good luck.
Donate and make this blog better
Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]
V1.9 Added Let’s Encrypt info
V1.8 added Troy Hunt article on CSP
v1.7 added link to Hardening a Linux Server link
V1.6 security