HTTP Security Headers
Learn how HTTP security headers provide protection against common vulnerabilities like Cross-Site Scripting and man-in-the-middle attacks.
We'll cover the following...
What are HTTP headers?
HTTP headers represent metadata associated with each HTTP request and response. Based on the type of information they contain, headers can be grouped into one of the following four categories:
Request headers: Information about the resource being fetched or about the client requesting the resource.
Response headers: Information about the response that doesn't relate to the HTTP message body.
Representation headers: Information about how the resource sent in an HTTP message body is represented (how the content is encoded, compressed, formatted, etc.). These headers are included in both the request and response.
Payload headers: Information about the safe transport and reconstruction of the original resource representation (transfer encoding, integrity checks, etc.). These headers are included in both the request and response.
Open the browser console, navigate to the “Network” tab, and refresh this page. Inspect a request to see the associated request and response headers as key/value pairs.
HTTP security headers are a classification of headers that directly relate to security. Not including security headers in server responses falls under the Security Misconfiguration OWASP category, ranked fifth on the OWASP Top Ten. Let's take a look at the most important HTTP security headers and how we can use them to prevent common vulnerabilities like XSS and man-in-the-middle attacks.
Response headers
Let's start with response headers that are also classified as security headers.
Content-Security-Policy (CSP)
We can use the Content-Security-Policy (CSP) header to restrict which inline scripts can be executed on a web page by using the script-src
directive to provide extra protection against XSS attacks. A strict, hash-based CSP (script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic'
) is recommended over an allowlist-based CSP (script-src www.googleapis.com
) because an allowlist-based CSP can be easily bypassed.
For example, observe the script below:
<script>console.log('hi');</script>
It hashes to 'sha256-BaqacLJJ+XuW7nqK6YVeA3VvI1BYJ2dGZoulLrJml2E='
, so our CSP header might look something like this:
Content-Security-Policy:script-src 'sha256-BaqacLJJ+XuW7nqK6YVeA3VvI1BYJ2dGZoulLrJml2E=' 'strict-dynamic' https: 'unsafe-inline';
In this example, https: 'unsafe-inline'
is used as a fallback for browsers that don’t support hash-based CSP with 'strict-dynamic'
.
CSP is set in the first HTTP request for the web page itself. Alternatively, CSP can be set with the meta
HTML element, which can be automated using module bundler plugins.
We need to load externally sourced scripts via an inline script wrapper because hash-based CSP for sourced scripts isn’t fully supported at the time of writing.
<script src="https://example.com/foo.js"></script><script src="https://example.com/bar.js"></script>
This means that the code above should be rewritten to match how it is ...