This article explores Content Security Policy and how a CSP header can help prevent common vulnerabilities.
What is Content Security Policy?
Content Security Policy directives are defined in HTTP response headers, called CSP headers. The directions instruct the browser on trusted content sources and include a list of sources that should be prevented. In addition, the Content-Security-Policy header declares content restrictions by specifying server origins and script endpoints.
CSP directives fall under various categories depending on use-case and content attribute. These include:
These directives specify the locations for loading certain resource types. Fetch directives include:
- child-src: defines the whitelisted script sources for browsing context loaded in frames and web workers.
- connect-src: specifies the URLs to be loaded using scripts
- default-src: the fallback directive for all fetch directives. This policy directive defines the default source list for other fetch directives.
- object-src: defines allowed sources for <applet>, <embed> and <object> elements
- style-src: provides a list of valid sources for cascading style sheets
Document directives help control the properties of the working environment or document where a policy will be effective. These include:
- sandbox: provides a sandbox for a specified resource similar to inline script elements.
- base-uri: specifies the URLs allowed in the document’s base element
These directives govern the locations of a form submission or where the document initiates any navigations. They include:
- form-action: specifies the URLs that act as targets for the submission of form elements
- frame-ancestors: restricts the parents to be embedded on the web page using the <frame>, <object>, <iframe>, <applet> and <embed> elements
These directives govern how CSP violations are documented and reported. They include:
- report-to: initiates a security policy violation event
- report-uri: a policy directive instructing the client environment to report any attempt to violate CSP specifications.
Other directives include:
- require-sri-for: enforces the use of Subresource Integrity (SRI) for the style attribute and page script sources
- trusted-types: used to specify a list of accepted, non-spoofable typed values, thus mitigating DOM-based XSS attacks
- require-trusted-types-for: this policy directive enforces the trusted-types policy on scripts that act as sinks for DOM-based XSS
- upgrade-insecure-requests: in websites with numerous insecure legacy URLs, this policy instructs the browser to treat every insecure URL as if it has been replaced with an HTTPS secure URL.
Why is CSP Header Relevant in Cyber Security?
A Content-Security-Policy header provides a framework for developers to control privilege and the loading of resources for the application process. It helps reduce the risk of attacks that leverage the need for loading resources within a malicious context. With properly formulated CSPs, the developers can access a reporting mechanism to detect and document security flaws exploited in production. All major browsers support CSPs, making the standard header an essential application security layer.
CSPs enable granular control over:
- Inline script execution
- How inline styles are applied
- Dynamic code execution
Vulnerabilities You Can Prevent Using CSP
CSPs protect web applications from several vulnerabilities and attacks, including:
CSPs form the first line of defense against XSS attacks as they block executing malicious scripts injected by untrusted sources. To reduce the XSS attack surface, developers restrict loading resources using the script-src ‘self’ directive. This directive only allows the page to load scripts originating from the same server hosting the page. The script-src <allowed-web-url> enables the page to load scripts from a specific domain. Besides whitelisting resource origins, CSPs help mitigate XSS attacks using hashes and nonces.
A nonce is a random value specified in the CSP so that it is used to load scripts in a tag. The CSP checks the nonce match source list, ensuring that the values match; otherwise, the script is executed. A hash-algo component of a trusted script’s contents can also be specified in a CSP directive. The script only runs when the actual script’s hash matches the value in the CSP directive.
The frame-ancestors ‘self’ CSP directive governs that only pages with the exact origin can frame the policy’s page. Developers can also wholly prevent framing using the frame-ancestors ‘none’ directive. CSPs can be used alongside the X-Frame-Options header to prevent clickjacking attacks. CSPs are more effective since they allow for the specification of multiple domains. The policy also validates every external resource in the parent frame hierarchy, enabling stronger protections against frame hijacking attacks.
Dangling markup attacks
CSPs protect against dangling markup attacks by restricting the page’s origin of images to be loaded. The img-src ‘self’ directive only allows images to be loaded from the exact origin. The img-src <allowed-web-url> directive governs the page to load images from a specific domain. The img tag helps prevent dangling markup attacks since it makes it easy to capture input data with minimal user interaction.
Testing the CSP involves examining the CSP meta element Content-Security-Policy HTTP response header in a proxy tool. Some insecure configurations to investigate include:
- The unsafe-eval directive that allows the use of eval() in the application
- Any unsafe-inline event handlers that may lead to the injection of malicious content into the webserver
- Any resources that can be loaded from any origin using the wildcard (*) source
- Using a wildcard (*) source for the frame-ancestors directive enabling framing for all origins
- Ensuring that a strict policy is applied for business-critical applications
The security researcher can also use tools such as the Crashtest Security Suite to check the strength of their security policies.
Examples of CSP Header
A few sample HTTP headers include:
Restricting content to the site’s origin
To ensure all content comes from the site’s origin, the web developer/administrator uses the Default-Src directive:
Content-Security-Policy: default-src 'self'
Enabling images from any origin
CSP allows for the specification of multiple policies for a resource by separating them using semicolons. For example, the developer can set user content to include images from any origin, restrict audio/video and load external scripts from a specific trusted server as shown:
Content-Security-Policy: default-src 'self'; img-src *; media-src darwin1.com darwin2.com; script-src darwincripts.example.com
Ensuring all content is loaded via TLS
Developers can prevent adversaries from eavesdropping on client requests by ensuring all of a website’s content is loaded using TLS. It is achieved using the security policy below:
Content-Security-Policy: default-src https://darwin.site.com
This policy ensures that the server only allows access to documents loaded through the single-origin https:darwin.site.com over HTTPS.