When it comes to client-side security, creating and deploying a content security policy (CSP) can serve as a solid starting point. To deploy a content security policy, you must first identify assets, including first- and third-party resources that will be loaded in the browser when a user visits your website. For those who haven’t heard of a content security policy (CSP), you probably know that it’s easier said than done.
Let’s talk about what those steps are to deploy a CSP. (And if you aren’t familiar with the process, don’t worry, we will cover the basics.)
This article includes two videos from our Content Security Policy series, which describe CSP basics and steps to create a policy.
Deploy a Content Security Policy: The Basics
What is a content security policy all about? Well, it’s a layer of security that acts as an “allowlist” when a user interacts with your website and web applications. For example, when a user visits your website the request is sent to the web server, and the server responds with all assets that should be loaded on that page. During this process, the system will execute scripts on the client side, i.e., first- and third-party scripts, images and other assets that load in the browser. There is risk here in the form of cross-site scripting (XSS) attacks, JS injection attack, formjacking, and data skimming attacks. In addition, poorly placed tracking code, while not malicious, may also be sending highly sensitive information to the wrong people. This is where a CSP will come in handy.
When the webpage request is sent, with a CSP header in place, all approved assets within the CSP, including first- and third-party resources, will return to be loaded by the browser. If a threat actor were to inject malicious code from a non approved resource, or if a tracker was placed adjacent to login credentials, for example, the CSP would see these as a non-authorized assets, and the malicious code would not load in the browser, resulting in a blocked threat.
When You Deploy a CSP, How Do You Reduce Threats?
So how can you reduce these types of threats and not miss this opportunity for domain level protection? You include the content security policy header on your website.
As a next step, you will add an additional header in the response. This is called the Content Security Policy header.
Website Response Header: Content-Security-Policy: <directive> <value>;
Inside of this header you have directives and values, and you can have multiple values in the same directive, as needed. After the semicolon, you can add the next directive. The values are your website’s assets. There is a great resource for directives on the Mozilla Developer Docs site to see which directives are available for the policy.
Adding a header in the response is actually quite simple, but identifying all the assets that should be part of the policy can get complicated and become burdensome quickly.
Identify Assets
In order to deploy a content security policy, you need to know which website assets are being loaded on your website.
Do you have a library of your website and web application assets? If not, there is a quick way to find out. You can deploy the most basic strict policy, in Report-Only mode, to get a list of violations from the browser console. That list of errors and violations are everything the policy would have blocked. Use this data to create the allowlist, i.e., the content security policy directives and values. The CSP will not be enforced when in ‘report-only’ and it can stay in this state for as long as needed.
Website Response Header: Content-Security-Policy-Report-Only = “default-src ‘self’;
Using the above method will get you a starting baseline, but you will have to chip away at the violations by adding them to your policy. Below is a sample policy, using only a couple directives. The ‘values’ represent your individual assets.
Content-Security-Policy:
default-src ‘none’;
img-scr ‘self’
value;
style-src ‘report-sample’ ‘self’ unsafe-inline’
Value
Value;
script-src ‘report-sample’ ‘self’ ‘unsafe-inline’ ‘unsafe-eval’
Value
Value
value;
There could be thousands of errors/violations; it could take many hours to shift through the data, and you might not end up with a complete policy. However, there is a more formal path to get a more complete policy.
Formal Process
The formal approach to creating and deploying a content security policy requires standing up a reporting engine to collect the violation reports. Using the report-uri directive in your policy will send all violations to the reporting endpoint. This is a must when you think about it. Websites are updated all the time. You may switch assets over time and malicious threats can be injected at any time. You need reporting to not only help build the policy, but also for maintenance and insight on potential risks.
Follow these steps to create and deploy a CSP:
- Develop a reporting API endpoint that would accept reported CSP events from browsers.
- This endpoint will collect the events, clear out invalid messages (with wrong format, for example), then store them in the database.
- Deploy this API endpoint and provision required data store.
- To deploy an API endpoint you either need to reuse existing web servers or deploy a new one.
- To provision a database you would need either your own database server or use available in-cloud solutions.
- Next step would be to test if the endpoint works as expected and indeed collects events and stores them in the database.
- After you have an API endpoint you can create your first CSP policy and use the endpoint’s url in [report-to] directive. The first CSP policy would be in the report-only mode, and quite restrictive. For example:
Website Response Header: Content-Security-Policy-Report-Only=default-src ‘self’; object-src ‘none’; report-uri <api-endoint-url?>
- Deploy the CSP policy on your main website.
- Allow some time to pass, collecting reported CSP violation events in the database.
- ‘Manually’ process collected CSP events:
- Write the routine or manually query database of the collected events.
- Parse the events and analyze violation reasons.
- Create a list of encountered sources per each of the CSP directives (script-src, ing-src, etc.).
- Create a new CSP policy based on the analyzed events.
- Use the list of the sources and directives from the previous step to manually write a valid CSP string.
- Deploy an updated policy and proceed to the next iteration.
Steps 6-8 would be repeated, to keep up with ongoing maintenance after a period of time. The good thing would be that the reporting database is a source to check for changes or not allowed assets.
I know what you’re thinking, this is a lot. But the benefits of having a content security policy are worth it. In some cases you may even be required to have this for compliance reasons.
Going further, once you enforce your policy by removing report-only from the header, the reporting data will show you what has been blocked from loading on your site. These violations should be added to update your policy or investigate further if there is a potential risk.
With growing attacks on the client-side everyday that impact web users directly, content security policies should not be ignored. Creating and deploying a content-security policy can be a daunting task, but there are tools out there that can assist with all steps of the process.
Alternatives to Manually Deploying a CSP
An automated content security policy is a purpose-built security solution to help manage content security policies on the front end—or on your client-side attack surface. An automated CSP removes the risks of manual CSP management by leveraging automation to add a layer of protection to your client-side security solutions.