code

HTTP Security Headers

Written by Itamar Rom on

HTTP Security Headers

Written by Itamar Rom on


Introduction

As web applications continue to utilize new and advanced technologies day by day, these technologies can sometimes introduce risks and unknowingly expose them to different vulnerabilities.

To achieve the goal of making applications as secure as possible, HTTP security headers are a small implementation that can make a huge difference. 

In this article, we will look at the recommended security headers according to OWASP and how they help us prevent security vulnerabilities such as Cross-site scripting (XSS), Clickjacking, Information disclosure, and more. We will also review some now deprecated headers as they are no longer relevant and may even pose a security risk to an otherwise secure application.

We will also discuss the importance of manual and automated testing and how to review web application security.

What Are Security Headers?

The main goal of security headers in HTTP communication is to enforce security for the users’ browsers by specifying rules and limitations when information is exchanged between a client and a server.

They provide an extra layer of security by restricting the insecure behaviors of modern browsers and preventing web applications from running into easily avoidable vulnerabilities. Even when seeking a balance between usability and security, some headers are simply considered industry best practices and will easily improve the security of any web application.

Let’s take a closer look at each header, explain their different directives, and review the recommended settings for each one:

1. X-Frame-Options

This header was created to improve the protection of web applications against clickjacking attacks. It declares a policy stating whether the browser may display the page’s contents when embedded using a frame in another website. It blocks any site from presenting the protected page’s contents inside of a “framing” element such as <frame>, <iframe>, <object>, and <embed>.

The X-Frame-Options header includes the following directives:

DENY 

The DENY  value will disallow displaying the contents in a frame completely. 

SAMEORIGIN (optional) 

Allows framing the contents only by pages of the same origin. If you wish to use this setting, consider that it may still introduce security issues as it doesn’t protect against attacks using multiple nested frames.

ALLOW-FROM (deprecated)

Permits embedding only by a specified domain. Do not use this option, as it is already deprecated. Modern browsers will completely ignore this header when used.

Recommended Setting
According to OWASP, the recommended value of this header is as follows:

X-Frame-Options: DENY

If possible, using the Content Security Policy (CSP) frame-ancestors directive is most recommended as it obsoletes the X-Frame-Options header, but in cases using CSP directives isn’t an option, X-Frame-Options: DENY  provides excellent protection against clickjacking attacks for most web applications.

2. Strict Transport Security

When a web server sends the HTTP Strict Transport Security (HSTS) header, it restricts web browsers from accessing the web application via an insecure HTTP connection by enforcing all interactions to be made using only HTTPS.  This behavior helps prevent Man In The Middle (MiTM) and cookie hijacking attacks from being performed on the application’s users.
The HSTS header includes the following directives:

Max-age  =  {seconds}

This directive is required and specifies the time in seconds the client should access the server using HTTPS by default. The recommended value is set to 2 years. Setting this value to 0 will cancel this behavior.

includeSubDomains

Specifying this optional, although recommended directive, will also enforce the policy on the host’s subdomains. This option is more secure, but understandably, it will block any attempt to serve a page’s content over HTTP.

preload

The preload directive helps enhance the header’s security but also has some repercussions that should be considered before implementation.

If the web application is accessed for the first time over HTTP, then the HSTS header will be ignored. Specifying the preload directive will enter your domain into the HSTS preload list, which is maintained by Chrome and used by other browsers. This will inform the browser that this domain should be accessed only using HTTPS. If you are not completely certain that you can serve your content over HTTPS in the long term, then consider that removing your domain from the preload list can be a lengthy process. Viewing the preload removal details before deciding whether to implement this directive is highly recommended.

Recommended Settings

The recommended settings for this header provided by OWASP are as follows:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
As mentioned above, the preload directive can be considered optional, as setting it does have repercussions. Leaving it out may be sufficient in most cases, but it should be included in the header settings for the best secure option.

It is also important to note that any misconfiguration of the header or technical issues with the SSL/TLS certificate can make the web application inaccessible to legitimate users. For example, suppose the certificate expires or is revoked before the header’s duration is over. In that case, users might be unable to access the application until the header duration expires.

3. X-Content-Type-Options

By setting the X-Content-Type-Options with the nosniff directive, which is the only directive available, the server blocks the browser from performing MIME sniffing and instructs it to strictly adhere to the content type declared by the server.
MIME sniffing is an action browsers perform to guess the content type of served media when it cannot be explicitly determined from the response. Each browser performs content sniffing differently. For example, Firefox will either look at contextual clues like the HTML element that triggered the fetch or inspect the magic bytes of the retrieved media.

This behavior can introduce security risks by opening an attack vector called MIME Confusion, which occurs when an attacker manipulates the content of a file to trick the browser into misinterpreting its MIME type. This attack vector includes potential exploits such as content spoofing, Cross-Site Scripting (XSS), and unintended execution of malicious client-side code. 

Recommended Setting

OWASP recommends including the X-Content-Type-Options header with the nosniff  directive as part of the HTTP security response headers
X-Content-Type-Options: nosniff

4. Content- Security- Policy

An entirely separate article can be written about this header, which is already considered a web security standard. While we’ll only touch on it briefly here, for a deeper understanding of its features, directives, and customization options, it is highly recommended to check out the OWASP Content Security Policy Cheat Sheet in the references section.

Content Security Policy (CSP) is a security feature used to specify the origin of the content allowed to be loaded in a web application (such as scripts, stylesheets, images, fonts, etc). This can be achieved by defining a set of directives that instructs the browser on what content is allowed and rules for how certain actions should be handled if a policy is violated. For example, a CSP directive might specify that only scripts from specific domains can be executed or that inline script blocks are not permitted. This can help prevent attackers from injecting malicious scripts into a website, as the browser will refuse to execute scripts that violate the policy.

CSP generally helps mitigate the risks of attacks such as Cross-Site Scripting (XSS), Clickjacking, and other client-side code injection attacks. It is more applicable to pages that render and execute scripts or code and less so for REST API responses, where the content returned is not being rendered.

Note that implementing a proper CSP requires careful tuning because, if enabled, CSP has a significant impact on the way browsers render pages.

Example Policy

There is no recommended setting, as the CSP use cases change with each application.

The following is a common restrictive example that covers potentially unsafe entities.

Content-Security-Policy: default-src ‘self’; frame-ancestors ‘self’;

script-src ‘self’; object-src ‘none’;

5. Referrer-Policy

The Referrer-Policy header controls how much referrer information should be included with requests (sent via the Referrer header).

Currently, the default behavior of browsers is to send full referrer information when viewing a page on the same origin (which includes the URL origin, path, and query string), but when sending cross-origin requests, the referrer header only includes the origin part of the URL.

This behavior is sufficient, but since some users might still be using older browsers or a more strict or permissive Referrer Policy is required, the Referrer Policy can be included as part of the response headers returned by the web application.

The Referrer-Policy header includes the following directives:

no-referrer

The sent requests will not include any referrer information.

no-referrer-when-downgrade

The full URL will be sent when the HTTP protocol security level stays the same or improves. It will limit the referrer information only when the connection is downgraded or even changed to a different protocol (may change on different browsers).

origin

It will only include the origin with sent requests.

origin-when-cross-origin

When cross-origin requests are made, only the origin will be included. this includes 

connection downgrading.

same-origin

A full URL will be sent when requests are on same-origin requests but when cross-origin 

doesn’t include any referrer information.

strict-origin

It will send the origin when the HTTP protocol security is not changed, and if 

downgraded, don’t include any referrer information.

Strict-origin-when-cross-origin (default)

This is the default browser behavior. It will send the full URL on same-origin requests 

and include only the origin on cross-origin requests. Also, if the connection is 

downgraded, referrer information will not be included.

Unsafe-url (unsafe)

It will include the entire URL on any request. Do not use this setting, as it can potentially

disclose sensitive information. 

Recommended Setting

The recommended setting for this header provided by OWASP is as follows:

Referrer-Policy: strict-origin-when-cross-origin

6. Clear-Site-Data

This header clears browsing data associated with the requesting website (cookies, storage, cache, etc). It gives developers more control over the data being stored by a client browser in the context of their owned origins, which is fetched from the response URL. It can be helpful when performing actions such as logging out a user, but keep in mind that this header shouldn’t be solely relied on and should be tested as different browsers provide different support for the header’s directives.

The Clear-Site-Data header includes the following directives:

“cache”

The browser will remove locally cached data (the browser cache). Depending on the browser used,  Additional cached data may also be removed.

“clientHits”

Indicates that the server wishes to remove all client hints (will be removed with “cache”, “cookies”, or “*” as well).

“cookies”

Using this directive will remove all cookies for the origin of the response URL from the browser and HTTP authentication credentials. This also includes all subdomains of the origin.

“storage”

Indicates that the server instructs the browser to remove all DOM storage for the origin.

“executionContexts”

Indicates that the server instructs the browser to reload all browsing contexts for the origin (like refreshing the current URL), currently only supported by a small subset of browsers

“*”

Will clear all types of data from the browser for the origin. Any future data types will also be covered as well.

Example Policy

The following example clears the browser’s cache, cookies, and storage for the origin:
Clear-Site-Data: “cache”, “cookies”, “storage”

7. Cache-Control

The Cache-Control header uses different directives to specify a resource’s caching behavior. It helps control whether and how caching is applied to that resource by browsers (client-side) and other intermediary caches such as proxy servers (server-side). It helps mitigate several cache-related attacks, such as Replay attacks, Session hijacking, Injection attacks, and Cache poisoning.

The Cache-Control header includes the following directives:

public

This directive allows the response to be cached by any cache, including both client-side and server-side caches. Cached responses marked as public can be served to subsequent requests from any user. When marking different types of content as public, careful consideration should be given to prevent unintended exposure of sensitive information.

private

Including the private directive means the response will be cached only to a single user (typically client-side) and should not be cached by shared caches, which means it will only be cached by the user’s browser or any other private cache associated with that user.

no-cache

Using no-cache does not mean that caching will not be performed. It indicates that the response can be cached, but the cached content must be revalidated with the origin server before it can be served, so both client-side and server-side caches can store the response, but they must check with the origin server to ensure the cached content is still valid before serving it. The revalidation of the content will be performed only when serving expired or stale content.

no-store

The no-store directive means caches cannot store the response. This is applied to all caches and is usually used when serving sensitive or dynamically generated content.

max-age

This directive specifies the maximum time (in seconds) the response can be cached. After the specified time has elapsed, the cached response is considered stale.

s-maxage

This directive is similar to the max-age directive but is applied specifically for shared caches. It will override any max-age or Expires header if present. 

must-revalidate

The must-revalidate directive is similar to the no-cache directive. The only difference is that the revalidation of the content will be performed on each request regardless of the content’s freshness.

proxy-revalidate

Similar to the must-revalidate directive, but applied specifically for shared caches. 

no-transform

The no-transform directive instructs shared caches not to modify the response’s content in any way. This includes preventing transformations like compression or encryption. 

It is particularly useful for resources like JavaScript files or images where it is important to ensure the integrity and structure of the data. 

Example Policy

The following example sets the caching behavior of that content to only use private caches, revalidate the content with the server when expired, and is immediately stale when served:
Cache-Control: private, no-cache, max-age=0

8. Cross-Origin-Embedder-Policy (COEP)

This header configures the embedding of cross-origin resources into the document. It controls whether a resource can be embedded using mechanisms like iframes or objects. It helps mitigate the risk of being exposed to cross-origin attacks and data leakage by preventing potentially unsafe cross-origin content from being embedded.

The COEP header includes the following directives:

unsafe-none (default)

This directive allows embedding content without restrictions. It does not require adhering to a CORS policy or the CORP header.

require-corp

This directive states that the document can only embed content from the same origin or cross-origin content explicitly marked as loadable. It also ensures that cross-origin embedded content can only load content from the same origin (content’s origin).  If not, it will be blocked by the COEP header. So be aware that any cross-origin resources not configured correctly will be blocked when this directive is set.

Recommended Setting

The recommended setting for this header provided by OWASP is as follows:

Cross-Origin-Embedder-Policy: require-corp

9. Cross-Origin-Opener-Policy (COOP)

The COOP header establishes boundaries between documents from different origins. It ensures that a top-level document does not share a browsing context group with any opened cross-origin content, for example, via iframe or popups.
Its main goal is to mitigate security risks associated with cross-origin interactions, which can cross the security boundary established by the Same Origin Policy (SOP), therefore protecting the integrity of the documents. This is applied to both the opener and the opened documents.

The COOP header includes the following directives:

unsafe-none (default)

This directive allows both the opened and its opener documents to be in the same browsing context group without cross-origin restrictions. If either of them has a COOP of same-origin or same-origin-allow-popups, they will be isolated.

same-origin-allow-popups

This directive will isolate the browsing context of the documents unless they are of the same origin. With this directive set, the opener document can open cross-origin content in a new window.

same-origin

The same-origin directive is the most restrictive. It will block any interaction with opened content unless it is of the same origin. The browsing context of both documents will be completely separate.

Recommended Setting

The recommended setting for this header provided by OWASP is as follows:

Cross-Origin-Opener-Policy: same-origin

10. Cross-Origin-Resource-Policy (CORP)

The CORP header controls whether certain resources, such as CSS, images, and scripts, can be fetched by the origin. It can tighten the Same Origin Policy to impose the same restrictions on these resources that are usually allowed to be fetched from different origins. This header’s primary goal is to mitigate security risks associated with loading resources from untrusted or potentially malicious origins.

CORP directives:

same-origin

Specifies that only requests from the same origin can fetch the resource using the Same Origin Policy.

same-site

This directive allows fetching resources only if they are from the same site.

Cross-origin (default)

If CORP is not specified, this is the default policy that the browser will follow. It permits unrestricted cross-origin resource fetching.

Recommended Setting

The recommended setting for this header provided by OWASP is as follows:
Cross-Origin-Resource-Policy: same-site

Testing Security Header Configurations

Reviewing your security header configurations is important in understanding the web application’s current security posture. There are several ways this can be done. One such way is performing an automated assessment using an open-source tool such as the Mozilla Observatory.
Mozilla Observatory is a user-friendly tool that can help assess the effectiveness of your security headers. The Observatory scans your web application and evaluates security-related practices, including implemented secure headers like CSP, HSTS, and more. To use the Mozilla Observatory, simply input your web application’s URL, and the tool will generate a detailed report highlighting strengths and areas for improvement.

Running the Observatory Security Assessment on an Example Domain

It is important to note that the test results are added to a public list saved online. To use this tool confidentially, download the Observatory Scanner and use a local installation to run your tests.

The Importance of Manual Testing

While automated tools like the Mozilla Observatory offer a convenient way to quickly overview your web application security configurations, it is important to acknowledge their limitations. These tools provide valuable insight but may not catch all the intricacies and nuances specific to your application. Therefore, conducting a more thorough and accurate manual assessment is important to ensure your web application security configurations are as effective as possible.

Conclusion

Implementing robust HTTP security headers is crucial in fortifying web applications against several potential vulnerabilities. Ensuring a comprehensive and up-to-date understanding of the latest and deprecated security headers is paramount for any organization committed to safeguarding its applications and users from potential threats.  

Organizations should prioritize cyber security risk assessments and penetration tests to mitigate risks in web application deployments, which have become increasingly popular among companies developing SaaS products. Clear Gate, a trusted cybersecurity provider, offers in-depth manual penetration tests to help organizations strengthen their security,  including security headers implementations discussed in this article, and, as a result, protect valuable data from potential threats.

References