Every website needs to be set up with a cloud service provider, but what about your other CSP: Content Security Policy?
The Content Security Policy (CSP) is a standard provided in an HTTP response header that helps prevent cross-site scripting attacks (XSS), clickjacking, packet sniffing, and malicious content injection on the client side of your web page. Configuring the [.rt-script]Content-Security-Policy[.rt-script] header will enable a CSP with the directives you supply to control how a user agent loads resources on your site. This post provides details about how a Content Security Policy works, how to configure your CSP, and common issues with CSP setup.
What is a Content Security Policy?
While input validation and output encoding are the first line of defense against code injection attacks, your Content Security Policy provides a layer to your defense-in-depth cybersecurity practices.
A [.rt-script]Content-Security-Policy[.rt-script] header defines directives for server governance on website behaviors through the HTTP header, though you can also supply HTML [.rt-script]meta[.rt-script] tags with a string-matching attribute that sets a CSP for the page. The HTTP header is the preferred and recommended method to ensure representation across resources, whereas the HTML element would be limited to the document in which it is set.
With your CSP, you define the approved origins for content that browsers will load on your website, such as JavaScript, CSS stylesheets, images, and more. Without a CSP, malicious actors can inject their preferred content into your website, such as injecting a malicious script in a cross-site scripting attack or manipulating user behavior through a clickjacking attack. XSS attacks and UI redress are two attack vulnerabilities that could be exploited without a Content Security Policy that defines authorized content sources.
When you create your policy, you will supply your preferred directives to define the behavioral policy for your content resources. If you use a content delivery network (CDN), you may want to set up both the Content Security Policy and Cross-Origin Resource Sharing (CORS).
How to Create a Content Security Policy
By adding the [.rt-script]Content-Security-Policy[.rt-script] HTTP header to your website, you configure this policy to protect your website. When you create your policy, you include a set of directives that provide additional specifications for how your site enables origin permissions with content on your website. This origin policy determines how the client-side browser can access resources.
To create the Content Security Policy for your website, you will need to update the configuration file containing your HTTP Response header. Different server setups and hosting platforms require different approaches to your configuration files. For example, you update the [.rt-script].htaccess[.rt-script] or [.rt-script].httpd.conf[.rt-script] files for Apache web servers, whereas NGINX servers require modification in the server block.
Use the Mozilla Developer Resources guide to the Content-Security-Policy to identify which CSP directives you may need for your site. Supply your preferred policy directives as a directive and value pair in a semicolon-separated list. The syntax for a Content Security Policy HTTP header is as follows:
[.rt-script]Content-Security-Policy: <directive> <value>; <directive> <value>[.rt-script]
Your policy should always include the [.rt-script]default-src[.rt-script] directive, which will provide a fallback for any undefined resource types. The [.rt-script]default-src[.rt-script] directive is often paired with the [.rt-script]'self'[.rt-script] value to define all content origination from only that site's own origin. In that circumstance, the policy would read as follows:
[.rt-script]Content-Security-Policy: default-src 'self'[.rt-script]
If you set [.rt-script]default-src 'none'[.rt-script], then you need to supply additional directives to allow some resources for specific tasks as no resources will load for instances with the [.rt-script]none[.rt-script] keyword. Beyond the [.rt-script]default-src[.rt-script] directive, you can determine which directives will suit your organization's needs.
As you prepare your header with allowed sources, be intentional about which sources are specified by your allowlist. Granular permissions will lower your attack surface, whereas broad permissions, such as a wildcard domain pointing to an Amazon S3 bucket, can widen your vulnerable attack surface. If an attacker knows your site is vulnerable and can identify your allowable sources, they could spin up their own wildcard subdomain from the same allowed source (such as an AWS S3 bucket) to load and inject malicious code into your wildcard entity. Tightened permissions for allowed sources can help to prevent this type of bypass attack.
Refer to the examples in the next section for commonly used directives as you define your CSP.
Sample CSP Headers
This section provides brief examples for some commonly used directives. Your CSP may include these or other directives, and these examples are provided as an educational resource. Be sure that you define a full Content Security Policy that meets your website's security requirements.
To allow content from a trusted domain and its subdomains, append the [.rt-script]self[.rt-script] value with the trusted domain and a wildcard identifying subdomains (replacing [.rt-script]your_domain[.rt-script] with your domain):
[.rt-script]Content-Security-Policy: default-src 'self' your_domain *.your_domain[.rt-script]
To ensure that all content is loaded using Transport Layer Security (TLS), prepend the domain with [.rt-script]https://[.rt-script] (replacing [.rt-script]example.com[.rt-script] with your domain):
[.rt-script]Content-Security-Policy: default-src https://example.com[.rt-script]
The [.rt-script]script-src[.rt-script] directive identifies allowable sources for JavaScript, including inline scripts, event handlers, and information held in [.rt-script]script[.rt-script] tags. If you don't provide a source for the [.rt-script]script-src[.rt-script] directive, it will fallback to the source allowed by your [.rt-script]default-src[.rt-script] directive. With this directive, you can supply a nonce-source or hash-source that dynamically generates a cryptographic token, which would allow an inline script when your policy would otherwise disallow it. The following CSP header would allow scripts from the self-origin and your domain:
[.rt-script]Content-Security-Policy: script-src 'self' https://your_domain[.rt-script]
Whereas if you generate a file hash, you would include that in both the directive and with an [.rt-script]integrity[.rt-script] attribute in your [.rt-script]script[.rt-script] tag. The policy would be similar to the following with your unique alphanumeric hash string:
[.rt-script]Content-Security-Policy: script-src 'sha384-your_alphanumeric_hash_string'[.rt-script]
You can specify allowed sources for different types of content using other directives, such as the [.rt-script]img-src[.rt-script] or [.rt-script]style-src[.rt-script] directives, depending on your web application's needs. If your site servers a large variety of content and you want to protect against content injection attacks, your [.rt-script]Content-Security-Policy[.rt-script] header can become lengthy to account for the distinctions made between different content sources.
As you set your policy, you might want to test the deployment in a reporting mode. Appending [.rt-script]-Report-Only[.rt-script] to the header will report any policy violations to a provided resource identifier (URI) without enforcing the policy itself. Instead of the [.rt-script]Content-Security-Policy[.rt-script] HTTP header, you would use the [.rt-script]Content-Security-Policy-Report-Only[.rt-script] header.
To enable reporting on your active policy, specify the [.rt-script]report-to[.rt-script] directive with the URI to collect CSP violation reports in the manner you set, such as in the following header (replacing [.rt-script]your_domain[.rt-script] with your domain):
[.rt-script]Content-Security-Policy: default-src 'self' your_domain; report-to http://reports.your_domain/collector.cgi[.rt-script]
You can then review your CSP reports to analyze how your content policy functions and identify any issues resulting from configuration. The [.rt-script]report-to[.rt-script] directive will replace the deprecated [.rt-script]report-uri[.rt-script] directive, though you can include both directives for compatibility across browsers that may not yet support [.rt-script]report-to[.rt-script].
Other commonly deployed directives include [.rt-script]base-uri[.rt-script] to govern [.rt-script]<base>[.rt-script] elements, [.rt-script]child-src[.rt-script] for nested browsing contexts, [.rt-script]connect-src[.rt-script] to restrict specific APIs and WebSockets, [.rt-script]font-src[.rt-script] for permitted fonts, [.rt-script]form-action[.rt-script] for form submissions, [.rt-script]frame-src[.rt-script] for [.rt-script]<frame>[.rt-script] and [.rt-script]<iframe>[.rt-script] elements, [.rt-script]media-src[.rt-script] for [.rt-script]<audio>[.rt-script] and [.rt-script]<video>[.rt-script] elements, and [.rt-script]object-src[.rt-script] for plugins like the [.rt-script]<object>[.rt-script] and [.rt-script]<embed>[.rt-script] elements.
Common Issues with CSP Configuration
You can perform manual validation review to gauge how your Content Security Policy is set up, or you can use a continuous monitoring tool like UpGuard BreachSight to automate your configuration review.
When BreachSight examines your website, our scanning techniques can identify common configuration issues that may occur during your CSP setup. BreachSight identifies the following findings related to CSP configuration:
- CSP is not implemented
- CSS implemented unsafely
- CSP contains unsafe-eval
- CSP allows insecure active sources
- CSP allows insecure passive sources
If you have not set the Content-Security-Policy header, you will receive the CSP is not implemented finding. To remedy this issue, establish the CSP header for your site and enable it on your server to prevent XSS and injection attacks.
If your CSP is not configured correctly or if you allow certain sources, then your site may remain vulnerable to certain injection attacks. Removing the [.rt-script]unsafe-inline[.rt-script] and [.rt-script]unsafe-eval[.rt-script] options from the CSP header to correct the CSP implemented unsafely and CSP contains unsafe-eval findings. Because [.rt-script]unsafe-inline[.rt-script] permits the use of inline resources and [.rt-script]unsafe-eval[.rt-script] allows dynamic code, a site with those directives remains vulnerable to XSS and injection attacks as attackers could insert malicious code like executable JavaScript.
Additionally, you should ensure your authorized sources are set correctly to allow only the specified server origins, script endpoints, and controlled resources. Implementing the [.rt-script]upgrade-insecure-requests[.rt-script] option will force the server to read all HTTP requests over HTTPS and otherwise block any insecure requests that cannot be upgraded.
In addition to the top-level notification, UpGuard identifies which assets have triggered this risk, when the issue was detected, and how the expected values compare to the actual header. When you know which website or IP address triggers these findings, you can then update the specific asset to ensure the correct configuration. After updating your assets, you can wait for UpGuard's daily scan or rescan the asset for a real-time update.
Once you know which of your domains or IP addresses need to have the Content Security Policy modified, you can update your CSP configuration settings.