WordPress-Server-Ubuntu-24.04
7 Nginx Hardening

Nginx Security Hardening for Running WordPress

This guide covers steps to improve the performance and security of your Nginx server, focusing on attacks like XSS, Clickjacking, and MIME sniffing. Each section explains what the attack is before diving into the Nginx configuration. Follow along to secure your WordPress installation and improve HTTPS performance.


1. Initial Security Scan

Before beginning, evaluate your site’s security by running basic security scans:

You may receive a low initial score for security headers, but we'll improve that as we proceed.

2. SSL Hardening

What is SSL Hardening? SSL Hardening is the process of configuring SSL/TLS to enhance security. While HTTPS protects communication, vulnerabilities in older SSL/TLS protocols can be exploited by attackers to intercept sensitive data.

Enforcing the use of strong protocols and disabling weak ciphers will secure your server. You can also add a Strict-Transport-Security (HSTS) header to force browsers to always use HTTPS, even if a user attempts to access the HTTP version.

Step 1: Configure Strict-Transport-Security

  1. Open the Nginx configuration file:

    sudo vim /etc/nginx/nginx.conf
  2. Add the following lines under the HTTP block to enforce HTTPS:

    ##
    # Security Headers
    ##
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
  3. Use the Mozilla SSL Configuration Generator (opens in a new tab) to fine-tune your SSL settings. Replace the ssl_protocols and ssl_ciphers lines:

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
    ssl_dhparam /etc/nginx/dhparam;
  4. Disable ssl_prefer_server_ciphers to allow clients to pick their preferred ciphers:

    ssl_prefer_server_ciphers off;
  5. Download the dhparam file for strong Diffie-Hellman parameters:

    sudo sh -c 'curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/nginx/dhparam'

    For more information on configuring Diffie-Hellman parameters, refer to this discussion (opens in a new tab).

  6. Test the Nginx configuration and reload it:

    sudo nginx -t
    sudo service nginx reload

3. SSL Performance Improvements

What is SSL Performance Optimization? SSL/TLS encryption adds some overhead, as servers need to establish secure sessions. Optimizing SSL helps to reduce the load on the server, making secure connections faster for users.

  1. To reduce the resource cost of SSL connections, open the main Nginx configuration file:

    sudo vim /etc/nginx/nginx.conf
  2. Add the following to enable SSL session caching:

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

4. OCSP Stapling

What is OCSP Stapling? OCSP Stapling (Online Certificate Status Protocol Stapling) is a technique used to enhance the performance and privacy of certificate revocation checks. Normally, browsers need to contact the certificate authority (CA) directly to check if a certificate has been revoked, which can introduce latency. OCSP Stapling allows the server to retrieve the OCSP response from the CA and attach it to the SSL/TLS handshake. This reduces the need for browsers to perform additional network requests, thereby improving the overall performance and privacy of your site.

Note on Certificate Permissions: When setting up SSL/TLS with Let's Encrypt and Nginx, it is important to manage permissions correctly. The www-data user, which Nginx runs as, needs read access to the SSL/TLS certificate and key files. However, it is neither necessary nor advisable to provide www-data access to the entire /etc/letsencrypt/live directory.

Key considerations for SSL/TLS certificate permissions:

  1. Permissions: Nginx needs read access to specific certificate and key files, not the entire directory.

  2. Certificate Files Location: Certificates and private keys are typically located in /etc/letsencrypt/live/yourdomain/. Nginx should reference these specific files.

  3. Permissions Setup: Ensure the following permissions for Nginx to read the certificate and key files:

    sudo chmod 644 /etc/letsencrypt/live/yourdomain/fullchain.pem
    sudo chmod 644 /etc/letsencrypt/live/yourdomain/privkey.pem
  4. Ownership: The files should be owned by root, allowing Nginx to read them.

  5. Security: The private key should be kept secure, with access restricted to necessary users only.

Step 1: Enable OCSP Stapling in Nginx

  1. Open the Nginx configuration file:

    sudo vim /etc/nginx/nginx.conf

    This file contains global settings for Nginx, including SSL/TLS configurations.

  2. Add or update the following directives within your server block to enable OCSP Stapling:

    ssl_stapling on;
    ssl_stapling_verify on;

    ssl_stapling on; enables OCSP Stapling, while ssl_stapling_verify on; ensures that the OCSP responses are validated.

  3. Specify the trusted certificate file for OCSP Stapling:

    ssl_trusted_certificate /etc/letsencrypt/live/yourdomain/fullchain.pem;

    This directive tells Nginx where to find the trusted certificate chain needed to verify the OCSP response.

  4. Configure the resolver for the OCSP query:

    resolver 8.8.8.8 8.8.4.4 valid=300s;

    The resolver directive specifies DNS servers (e.g., Google’s DNS servers 8.8.8.8 and 8.8.4.4) that Nginx will use to resolve domain names for OCSP queries. The valid=300s parameter sets the validity of DNS cache for 300 seconds. This step is necessary because OCSP Stapling requires Nginx to resolve the domain names of the CA to fetch the OCSP responses.

  5. Test the configuration and reload Nginx:

    sudo nginx -t
    sudo service nginx reload

By configuring OCSP Stapling, you improve the efficiency of certificate status checks and enhance the security of your SSL/TLS implementation. Ensure that certificate permissions and security settings are properly managed to maintain a secure and functional setup.

5. Cross-Site Scripting (XSS)

What is XSS? Cross-Site Scripting (XSS) is a vulnerability where attackers inject malicious scripts into webpages viewed by other users. This can lead to stolen cookies, session hijacking, or defacing websites.

To protect against XSS attacks:

  1. Follow WordPress VIP’s XSS validation guide (opens in a new tab) to validate and sanitize user inputs.

  2. Add a Content-Security-Policy (CSP) to block non-HTTPS assets:

    add_header Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval';" always;
  3. For tighter control, allow certain external assets like Google Analytics:

    add_header Content-Security-Policy "default-src 'self' https://*.google-analytics.com https://*.googleapis.com https://*.gstatic.com https://*.gravatar.com https://*.w.org data: 'unsafe-inline' 'unsafe-eval';" always;
  4. Enable XSS protection headers:

    add_header X-Xss-Protection "1; mode=block" always;

6. Clickjacking Protection

What is Clickjacking? Clickjacking is an attack where a user is tricked into clicking something different from what they perceive, often by embedding your website in a hidden iframe. This can lead to unintentional clicks on malicious content.

Prevent this by adding the X-Frame-Options header to block your site from being embedded:

  1. Add this header to your Nginx configuration as recommended by Troy Hunt (opens in a new tab):

    add_header X-Frame-Options "SAMEORIGIN" always;

7. MIME Sniffing Prevention

What is MIME Sniffing? MIME sniffing allows browsers to determine file types from content, potentially exposing your site to “drive-by” downloads. Prevent MIME sniffing by telling the browser to trust the MIME types you declare.

  1. Add this header to stop browsers from MIME sniffing, as recommended by Microsoft (opens in a new tab):

    add_header X-Content-Type-Options "nosniff" always;

8. Referrer Policy

What is a Referrer Policy? The Referrer Policy controls what information is sent in the Referer header when users navigate between sites. Reducing the amount of information shared protects user privacy and site security.

  1. Limit the referrer information shared with external sites, as explained by MDN (opens in a new tab):

    add_header Referrer-Policy "origin-when-cross-origin" always;

9. Permissions Policy

What is a Permissions Policy? Permissions Policy (formerly known as Feature Policy) allows you to control which browser features are enabled on your site, like geolocation, camera access, and microphone usage.

  1. Use a Permissions-Policy (opens in a new tab) header to restrict browser features:

    add_header Permissions-Policy "geolocation=*, camera=(self 'https://example.com'), microphone=()" always;

10. Final Security Scan

After applying these changes, verify your server’s security by re-running the scans:

Note: On SecurityHeaders (opens in a new tab) I received the following warnings though my score was an A:

  • Content-Security-Policy This policy contains 'unsafe-inline' which is dangerous in the default-src directive. This policy contains 'unsafe-eval' which is dangerous in the default-src directive.
  • Referrer-Policy The "origin-when-cross-origin" value is not recommended.

This concludes the Nginx security hardening guide. By following these steps, you’ll improve both the security and performance of your WordPress site. Proceed to the next chapter for moving a WordPress site with minimal downtime.