From 3bcaa5be2891bd36b5d224ac12135b997fe9c0ce Mon Sep 17 00:00:00 2001 From: Marcel Straub Date: Sun, 16 Jan 2022 22:13:54 +0100 Subject: [PATCH] Added documentation about hardening nginx --- content/docs/services/_index.md | 0 content/docs/services/hardening-nginx.md | 181 +++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 content/docs/services/_index.md create mode 100644 content/docs/services/hardening-nginx.md diff --git a/content/docs/services/_index.md b/content/docs/services/_index.md new file mode 100644 index 0000000..e69de29 diff --git a/content/docs/services/hardening-nginx.md b/content/docs/services/hardening-nginx.md new file mode 100644 index 0000000..0590c53 --- /dev/null +++ b/content/docs/services/hardening-nginx.md @@ -0,0 +1,181 @@ +--- +title: Hardening nginx +descriptions: Hardening of the nginx configuration. +summary: Do not expose the used server version and only use secure ciphers for https. +weight: 1 +categories: +- security +tags: +- nginx +- hardening +- ssl +- tls +--- + +# General information +- After you change the nginx configuration always test its validity by executing +```shell +nginx -t +``` +- Limit everything to what is needed for proper function. Do not use nice-to-have modules/configs that do not bear any usage for the user. + +# Have logging and monitor it +Logs help you identify and analyse attacks. So use them. But collecting only does not help, you must regularly analyse them. +```nginx +server { + # ... + error_log .../error.log warn; + access_log .../access.log combined; + # ... +} +``` +If collecting logs, keep *GDPR* in mind and only keep them as long as it is really required for securing the server. + +> I'm still looking-out for a good log management tool that helps to identify threats. + +# Don't expose server version +Exposed server versions make it easier for attackers to find weaknesses of your system, so give them as few information about your system as possible. +- Set ``server_tokens off`` in the ``http`` section of your ``nginx.conf``, e.g.: +```nginx +http { + # ... + server_tokens off; + # ... +} +``` +- Verify that nginx config is still valid (see sec. [General information]({{< relref "hardening-nginx.md#general-information" >}})) +- Reload configuration +```shell +$ systemctl reload nginx +``` + +# Limit HTTP methods +Limit to what you need, e.g. GET only is enough for that simple blog: +```nginx +location / { + limit_except GET { deny all; } +} +``` + +# Use secure TLS/SSL configuration +As of January 2022, the following configuration is considered as safe: +```nginx +server { + # ... + ssl_protocols TLSv1.2 TLSv1.3; + ssl_dhparam /etc/nginx/dhparam.pem; + ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM'; + ssl_prefer_server_ciphers on; + ssl_stapling on; + ssl_stapling_verify on; + ssl_session_timeout 10m; + ssl_session_cache off; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; + # ... +} +``` + +## Create Diffie-Hellman parameters file +Create your own set of Diffie-Hellman (DH) parameters for the key exchange and don't use the parameters commonly distributed with your Linux distribution. Weak DH parameters were a reason for past issues, cf. [Logjam Attack](https://weakdh.org/). + +You can create your own 4096 bit DH parameter set like this +```shell +$ openssl dhparam -out /etc/nginx/dhparam.pem 4096 +``` + +## SSL Protocols +- Protocols older than v1.2 are [deprecated by IETF](https://datatracker.ietf.org/doc/rfc8996/) +- Good write up why not to use older TLS versions can be found [here](https://www.venafi.com/blog/why-its-dangerous-use-outdated-tls-security-protocols). + +## Let the server decide on the cipher suite +As I harden the server and am possibly more upto date than some browsers out in the wild, my server knows best which ciphers to use. Therefore, use the following option +```nginx +ssl_prefer_server_ciphers on; +``` + +### Verification +You can use ``nmap`` with the ``ssl-enum-ciphers`` script. At least for Ubuntu it is already itegrated into the main packages: +```shell +$ nmap -6 --script ssl-enum-ciphers -p 443 blog.straubs.eu +Starting Nmap 7.80 ( https://nmap.org ) at 2022-01-16 21:42 CET +Nmap scan report for blog.straubs.eu (2a01:4f8:c2c:b754::1) +Host is up (0.036s latency). +Other addresses for blog.straubs.eu (not scanned): 116.203.209.149 +rDNS record for 2a01:4f8:c2c:b754::1: vpn.straubs.eu + +PORT STATE SERVICE +443/tcp open https +| ssl-enum-ciphers: +| TLSv1.2: +| ciphers: +| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A +| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A +| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (ecdh_x25519) - A +| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A +| compressors: +| NULL +| cipher preference: server +|_ least strength: A + +Nmap done: 1 IP address (1 host up) scanned in 1.30 seconds +``` + +[SSL Labs](https://www.ssllabs.com/ssltest/index.html) is also a great utility to check the overall security hardening on a protocol and header level. + +## Ciphers +An uptodate secure cipher list can be found add [syslink.pl](https://syslink.pl/cipherlist/). + +## OSCP stabling +OSCP stapling is well explained in [this Mozilla tech-blog article](https://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox/). Roughly spoken, the server you are connecting to also includes current evidence that its certificate is not revoked by the signing CA. Thus it reduces the round-trip time for the client as it would be the clients job to request this information at the CA. + +### Verification +You can verify the proper functioning of your setup with openssl: +```shell +$ openssl s_client -connect blog.straubs.eu:443 -servername blog.straubs.eu -status 2>&1 | grep -i ocsp +``` +Mind that you need to specify the servername option as well as the connection option if you use server name indication (SNI), e.g. if you host multiple domains on your server. +In case of success the output should look like this +```shell +OCSP response: +OCSP Response Data: + OCSP Response Status: successful (0x0) + Response Type: Basic OCSP Response +``` + +## SSL Session Cache +As NGINX does not provide any means of regularly cleaning up the session and ticket cache, it is best to turn it off +```nginx +ssl_session_cache off; +ssl_session_tickets off; +``` +That's important because to correctly implement [forward secrecy](https://en.wikipedia.org/wiki/Forward_secrecy) (PFS) the short-term secret, i.e. unique session keys, must not fall in the hands of an attacker. Therefore, it must be deleted/swapped regularly otherwise PFS is undermined. +Besides disabling the caches at all, one could also regularly recreate the session ticket key (see [Stephan Herber - Sichere TLS Konfiguration mit NGINX](https://www.sherbers.de/sichere-tls-konfiguration-mit-nginx/)). + +# Add security headers +My current defaults: +```nginx +server { + # ... + add_header Strict-Transport-Security "max-age=63072000; preload;"; + add_header X-Frame-Options "SAMEORIGIN"; + add_header Content-Security-Policy "default-src 'self'" always; + # ... +} +``` +## HSTS +- [Mozialla developer information](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) +- Tells browser always to use secure, i.e. https, transport +- On the page for ``domain.tld`` you can also set ``includeSubDomains`` options. This enforces for all subdomains of your domain secure transport. +- If you also want to be preloaded as HTTPS only, you can submit your own domain to the Google operated service [hstspreload.org](https://hstspreload.org/). +## X-Frame-Options +- [Mozilla developer information](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) +- Indicates if a browser is allowed to render a page from this server in a frame, iframe, embed or object tag. +## Content Security Policy (CSP) +- [Mozilla developer information](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) +- Helps to mitigate cross-site scripting +- Tells browsers which resource sources are acceptable to render this page +- Can request to report violations by providing a report-uri. For details see [Moziall developer information](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#violation_report_syntax). +```nginx +add_header Content-Security-Policy "default-src 'self'; report-uri https://collector.straubs.eu/collector" always; +```