Home Blog WordPress Security Configuring HTTP security headers on WordPress
Configuring HTTP security headers on WordPress

Configuring HTTP security headers on WordPress

HTTP security headers are a great way to improve the security of your WordPress site. Their job is to protect the integrity of requests and responses. Modern browsers support a variety of HTTP security headers. They protect your visitors from different types of browser attacks, such as clickjacking, cross-site scripting, and other common attacks. They even improve your siteโ€™s visitorsโ€™ privacy online.

In this article, we will look at what these HTTP security headers are, explain how they work, and how you can add these headers to your website to improve your WordPress siteโ€™s security.

What are WordPress security headers?

When we talk about WordPress security headers, we’re really talking about HTTP security headers. Think of HTTP headers as packets of information the web server sends clients. This information is not visible to the user but affects how information is processed.

HTTP security headers are independent of WordPress. They work in the same way in WordPress as they do for any other kind of website.

HTTP headers are specified in RFCs (Request for Comments); documents in which the specifications are laid out. As such, if you want to dive into the technical details of a particular header, all you need to do is refer to the corresponding RFC.

Security headers, in particular, specify the security-related settings of HTTP communication between a web client (your website visitors) and a server (your WordPress server). Enabling security headers on your WordPress website can improve your websiteโ€™s resilience against common attacks, including cross-site scripting (XSS) and clickjacking.

How HTTP security headers can improve WordPress security

HTTP security headers can help improve your WordPress websiteโ€™s security by instructing the browser to enable a variety of security features. Implementing headers requires some planning. Some headers have been deprecated and replaced by newer variants. However, older browsers may not implement these newer headers correctly. As an example, Internet Explorer 11 does not fully support CSP (Content Security Policy).

As such, it is considered best practice to test any changes in a testing or staging environment before applying any changes on a live WordPress site.

Pro tip: If you have analytics on your website, you should be able to get a pretty good idea of which browsers your users and visitors are using. This can help you run more relevant tests and use only those headers that are supported by these browsers.

The most commonly used HTTP security headers

Which headers do what? Letโ€™s dive into an overview of some of the most important and commonly used HTTP security headers.

Strict-Transport-Security header (HSTS)

The Strict-Transport-Security HTTP header instructs the browser to enforce HTTP Strict Transport Security (HSTS). HSTS instructs the visiting browser to always access the site over HTTPS (instead of HTTP), even if the user (or an attacker trying to run a Man-in-the-Middle attack) tries to access the site over HTTP. 

When using this header, the browser will always switch to HTTPS. As such, you should only enable HSTS if you have HTTPS enabled and fully working without mixed-content issues.

The following HTTP Strict Transport Security (HSTS) header enables HSTS for the duration of 1 year (31536000 seconds).

Strict-Transport-Security: max-age=31536000

Why is HSTS important?

It is very difficult for a bad actor to run a man-in-the-middle attack when you’re using HTTPS. Since data is encrypted, it is nearly impossible to read. As such, they’ll attempt to downgrade the connection to HTTP so that they can read the data.

When using the HSTS header, the browser refuses to connect over HTTP, rendering the attack useless.

Content-Security-Policy header (CSP)

The Content-Security-Policy HTTP security header is an HTTP header with a lot of power and configuration options. It configures the browserโ€™s Content-Security Policy (CSP), which is a set of security features found within modern browsers. They provide an additional layer of security that helps detect and mitigate attacks such as Cross-Site Scripting (XSS) and data injection attacks.

Content-Security-Policy (CSP) is also notoriously tricky to get right. This is because the right CSP settings will vary widely depending on the website in question. As such, it should be heavily tested before deployment โ€” so much so that it has a sister Content-Security-Policy-Report-Only HTTP header used just for testing CSP.

The following is an example of a pretty simple Content Security Policy (CSP) that only allows loading assets from the origin from which the website is served.

Content-Security-Policy: default-src 'self'

However, Content-Security-Policy (CSP) is much more configurable than shown in this simple example. CSP includes other directives, such as script-src, style-src, and img-src, to specify sources from which the browser may load assets (for example, CSS, images, and fonts).

X-Content-Type-Options header

The X-Content-Type-Options HTTP security header is a non-standard header. It is respected by all major browsers and prevents Cross-site Scripting (XSS) attacks caused by MIME-type sniffing. When present, this header tells the browser to strictly follow the MIME types defined in the Content-Type HTTP header. It also tells the browser that it should not try to detect the correct MIME type for the response data itself. The header has a single directive โ€” nosniff.

X-Content-Type-Options: nosniff

X-Frame-Options header

The X-Frame-Options HTTP security header has now been largely replaced by the frame-ancestors Content Security Policy (CSP) directive. While it is advised to use CSP with the frame-ancestors directive in place of X-Frame-Options, using both ensures wider compatibility with different browsers.

It was first introduced by Microsoft Internet Explorer (and adopted by other browsers with varying degrees of uniformity and compatibility) to protect browsers against Cross-site Scripting (XSS), Clickjacking, and other attacks that rely on a website being placed inside of an iframe.

There are two options available:

DENY: Used to prevent the website from being embedded in a frame or iframe

X-Frame-Options: DENY

SAMEORIGIN: Allows the website to be placed in a frame as long as the request comes from the same domain of the website.

X-Frame-Options: SAMEORIGIN

Referrer policy header

The referrer policy header controls how much of the referring URL is shared. In principle, this header enables you to balance user privacy with analytics and marketing requirements. Here, you need to pay special attention to which data you share. For example, you need to be careful not to share user or session IDs with third-party websites since this might compromise user privacy and security.

There are a few options available for setting the referrer policy header, including:

No Referrer: Does not share any information at all and guarantees maximum user privacy

Referrer-Policy: no-referrer

No Referrer When Downgrade: Does not send any data whenever the user navigates from an HTTPS page to an HTTP page.

Referrer-Policy: no-referrer-when-downgrade

Same Origin: Restricts data sharing to navigation within the same origin, which includes domain, protocol, and port.

Referrer-Policy: same-origin

Strict Origin: Takes Same Origin to the next level and restricts data sharing to navigation within the same origin and security level.

Referrer-Policy: strict-origin

Expect-CT header (Certificate Transparency)

Certificate Transparency is a mechanism through which SSL/TLS certificates are verified with a CA (Certificate Authority). Its goal is to ensure certificates have not been fraudulently issued and are not being misused. When set, the header tells browsers that the TLS certificate is CT-compliant, that is to say, is logged with a CA.

The Expect-CT header takes a number of attributes, including:

  • enforce: Enforces the policy
  • max-age: Time policy should be cached for
  • report-uri: URL for reporting policy failures
Expect-CT: enforce, max-age=86400, report-uri="https://melapress.com/example/report"

X-XSS-Protection header (Deprecated)

The X-XSS-Protection HTTP security header was a non-standard header. It was introduced to enable or disable browser protections against Cross-site Scripting (XSS) attacks. In practice, the XSS protection security header was easy for attackers to bypass and, as a result, is ignored by most modern browsers.

Public-Key-Pins

The Public-Key-Pins HTTP security header is used to configure the Public Key Pinning (HPKP) security feature. It was introduced in Google Chrome and Firefox to prevent TLS certificate spoofing. HPKP worked by having the web server provide the browser with a set of cryptographic hashes of the TLS certificate public keys the website used. The browser would then use it to compare with the certificates it receives from the server in subsequent requests. The problem was that HPKP was fairly complicated to manage and frequently resulted in misconfigurations that could completely disable website access. As such, it is no longer recommended to use it.

How to view your website’s security headers

Before you start considering which security headers to implement, you might first want to check which headers, if any, are already active on your website.

You can use tools like Security Headers to see which security headers are currently active.

Adding HTTP Security Headers in WordPress

HTTP security headers work best when configured on your web server or, where applicable, your Content Delivery Network (CDN) or Web Application Firewall. This allows them to be sent on each request. Alternatively, while less ideal, you can use a WordPress plugin to set these headers for you.

Now that we have covered the purpose of HTTP security headers, here are a few ways in which they can be enabled on your WordPress website.

  • Apache .htaccess file
  • Nginx configuration file
  • functions.php
  • Plugin
  • CDN

Adding HTTP security headers in WordPress using Apache HTTP Server

If your WordPress sites are hosted on an Apache web server, you can add HTTPS security headers directly to the .htaccess file. The main advantage here is that any policies configured are automatically applied to any HTTP response the server sends, including responses from WordPress.

The easiest way to access your htaccess file is through SFTP, either through a client such as FileZilla or through your hosting provider’s backend. You can also access the file through SSH and edit it using a CLI editor such as nano or vim.

Sample security header configuration

The following is an example of the configuration for the Apache HTTP Server required to enable a number of security headers, based on what we covered earlier.

<IfModule mod_headers.c>
    # X-Frame-Options to prevent clickjacking
    Header set X-Frame-Options "SAMEORIGIN"
    # X-Content-Type-Options to prevent MIME-type sniffing
    Header set X-Content-Type-Options "nosniff"
    # Strict-Transport-Security to enforce HTTPS
    Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    # Content-Security-Policy to control resources loaded on the page
    Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://trusted-scripts.com"
    # Referrer-Policy to control how much referrer information is shared
    Header set Referrer-Policy "no-referrer-when-downgrade"
    # X-XSS-Protection to enable basic XSS protection (for older browsers)
    Header set X-XSS-Protection "1; mode=block"
</IfModule>

Adding HTTP security headers in WordPress using Nginx

On the other hand, if you’re using Nginx as your web server, you can update the Nginx configuration file in a similar fashion as Apache’s htaccess file.

Similarly, the following is an example of the configuration for Nginx:

server {
    listen 443 ssl;
    
    # X-Frame-Options to prevent clickjacking
    add_header X-Frame-Options "SAMEORIGIN";
    # X-Content-Type-Options to prevent MIME-type sniffing
    add_header X-Content-Type-Options "nosniff";
    # Strict-Transport-Security to enforce HTTPS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
    # Content-Security-Policy to control resources loaded on the page
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://trusted-scripts.com";
    # Referrer-Policy to control how much referrer information is shared
    add_header Referrer-Policy "no-referrer-when-downgrade";
    # X-XSS-Protection to enable basic XSS protection
    add_header X-XSS-Protection "1; mode=block";
}

Adding HTTP security headers in the functions.php file

Adding your WordPress security headers to the functions.php file is another option that might be easier than editing the htaccess file or Nginx configuration file. However, do keep in mind that the functions.php file is theme-specific. As such, if you switch themes, the configured security headers will not remain active.

You can access the functions.php file in a number of ways including SFTP or SSH. Unlike the two methods covered previously, you can also add the headers through wp-admin. Simply navigate to Tools > Theme File Editor and edit your functions.php file.

Editing your functions.php file is not recommended. Instead, you should create a child theme or make changes in a testing/staging environment first.

Whichever way you decide to edit the file, you can add the security headers by creating a function and specifying the security headers you want to use within that function, as shown in the example code below:

function add_security_headers() {
    // X-Frame-Options to prevent clickjacking
    header('X-Frame-Options: SAMEORIGIN');
    // X-Content-Type-Options to prevent MIME-type sniffing
    header('X-Content-Type-Options: nosniff');
    // Strict-Transport-Security to enforce HTTPS
    header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
    // Content-Security-Policy to control resources loaded on the page
    header("Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-scripts.com");
    // Referrer-Policy to control how much referrer information is shared
    header('Referrer-Policy: no-referrer-when-downgrade');
    // X-XSS-Protection to enable basic XSS protection
    header('X-XSS-Protection: 1; mode=block');
}
add_action('send_headers', 'add_security_headers');

Adding HTTP security headers in WordPress using a plugin

Alternatively, while less effective (since it relies on WordPress itself to modify headers), using a WordPress plugin might be the easiest way to add HTTP security headers to your WordPress website. Plugins such as the Redirection plugin allow you to add custom HTTP headers to your website.

Adding HTTP security headers in WordPress through your CDN

Many CDNs (Content Delivery Networks) include an option to add HTTP security headers through their settings. There are two main advantages to specifying security headers at the CDN level:

  • The CDN will always serve the security headers
  • Since requests are handled by the CDN, WordPress server performance does not take a hit

The exact procedure for adding HTTP security headers at the CDN level will vary from one provider to the next. In Cloudflare, for example, you can add them by navigating to Rules and then creating a page for the domain you want to add HTTP security headers to.

Which security headers should you add in WordPress?

There are no hard and fast rules when it comes to security headers in WordPress. As such, every administrator is free to implement those security headers that address any security concerns they might have. Having said that, you can implement security headers in WordPress based on best practices recommendations as follows:

# Strict-Transport-Security (HSTS)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# Content-Security-Policy (CSP)
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-scripts.com
# X-Frame-Options
X-Frame-Options: SAMEORIGIN
#  X-Content-Type-Options
X-Content-Type-Options: nosniff
# Referrer-Policy
Referrer-Policy: no-referrer-when-downgrade
# X-XSS-Protection
X-XSS-Protection: 1; mode=block
# Access-Control-Allow-Origin (CORS Header)
Access-Control-Allow-Origin: https://trusteddomain.com
#Expect-CT
Expect-CT: enforce, max-age=86400, report-uri="https://example.com/report"

Dissecting each security header

Let’s have a quick look at each of the recommended security headers, their directives, and the role they play in securing WordPress:

  • HSTS: Forces the browser to use HTTPS and caches the policy for a year, enables any sub-domains to inherit the policy. It also allows the website to be included in a list of HSTS-preloaded sites.
  • CSP: Acts as an XSS protection security header by preventing malicious scripts from running on the site. It reports any violations to help identify vulnerabilities. Do note you’ll need to substitute https://trusted-scripts.com with your trusted domain.
  • X-Frame-Options: Prevents clickjacking and only allows framing from the same WordPress domain.
  • X-Content-Type-Options: The nosniff option forces browsers to follow the content type in the headers, thus preventing attacks.
  • Referrer-Policy: The referrer policy is primarily there to protect visitor privacy. The directive preventing data from leaking to unsecured (HTTP) pages.
  • X-XSS-Protection: This XSS protection security header protects older browsers by blocking XSS attacks.
  • Access-Control-Allow-Origin (CORS Header): Defines which domains can access your website resources. Do note you’ll need to substitute https://trusteddomain.com with your trusted domain.
  • Expect-CT: Enforces certificate transparency and reports issues so that corrective measures can be taken.

It is important to note that the above list is provided for indicative purposes only. Your requirements may vary. Keep your needs in mind when you add HTTP security headers for your WordPress site.

Frequently Asked Questions

What are security headers in WordPress?

Security headers in WordPress refers to HTTP security headers used in the context of a WordPress website. While there are no WordPress-specific headers, you can add any security headers through the web server configuration file, the functions.php file, or your CDN if you are using one.

How to add Content-Security-Policy header in WordPress?

There are a number of options for adding the Content-Security-Policy header in WordPress. If you have SFTP or SSH access you can add them to your WordPress server configuration files. Another option is to add the HTTP security headers to the functions.php file. However, changing the team will also remove the headers. Another option is to specify them in your CDN.

What security headers should I use?

There are no rules as to which headers should be used for any given website. However, security headers such as HSTS and CSP offer great security and should be at the top of your list. Other options include X-Frame-Options, X-Content-Type-Options, and Referrer-Policy. Refer to the article for more security headers you can implement on your WordPress website, including sample code.

FIELD:
Joel Barbara Avatar