Active content on websites (i.e. JavaScript, CSS, ActiveX) can be a security risk for internet users and website operators since they can be ma­nip­u­lat­ed by cross-site scripting. The Content Security Policy (CSP) was in­tro­duced to ensure that internet sites could be used to their full extent without having to worry about any security risks. The security standard is designed to protect against malicious attacks and is now supported by most web browsers. The security concept protects both websites and internet users. But what is behind it and how does CSP work?

De­vel­op­ment of the Content Security Policy

The Content Security Policy dates back to 2004 when it was still known as 'Content Re­stric­tion'. The reason for this effort was an in­creas­ing number of vul­ner­a­bil­i­ties in internet scripts. Cross-site scripting (XSS) is a criminal method of in­fil­trat­ing malicious code into a website, and poses a major risk for users. Users access a trust­wor­thy website, but there is a script running that loads malicious data from an external source. Cyber criminals often make use of security vul­ner­a­bil­i­ties in the website’s com­men­tary functions. By doing this, they can gain access to personal computers without internet users knowing it. Website operators won’t even notice that strange code has been in­tro­duced.

To solve this problem, the Mozilla Foun­da­tion promoted the de­vel­op­ment of the CSP. The advantage behind the security standard is that rules can be set up in the browser to tell the software which scripts it is allowed to load and which it isn’t. To do this, the Content Security Policy uses HTTP headers.

Fact

The Mozilla Foun­da­tion is behind the de­vel­op­ment of the Firefox browser. The non-profit or­ga­ni­za­tion is re­spon­si­ble for the ori­en­ta­tion of Mozilla’s projects and in­no­va­tions to do with the internet. The Foun­da­tion was founded by former Netscape employees, who developed one of the first web browsers.

How does the Content Security Policy work?

When com­mu­ni­cat­ing online, clients and server exchange data via the Hypertext Transfer Protocol (HTTP). HTTP header fields are an important part of the requests and responses: pa­ra­me­ters and arguments are trans­ferred in these, which are important for ex­chang­ing in­for­ma­tion between the two call par­tic­i­pants (server and client). They are generally divided into inquiry and response fields, and can contain in­for­ma­tion such as character set, language, and cookies. CSP is im­ple­ment­ed as a response header field. This means that the server delivers the in­for­ma­tion and the browser processes it. The Content Security Policy header is created by the website operator and inserted on every subpage of the website where you want the security standard to be applied. As the operator of the website, you have the pos­si­bil­i­ty of defining different security pre­cau­tions for each in­di­vid­ual page. You can implement the security concept more easily by creating .htaccess files, which are located in the same (or hi­er­ar­chi­cal­ly higher) folders as the cor­re­spond­ing web pages, or by embedding CSP directly into the server con­fig­u­ra­tion.

Note

If you want to check whether your browser supports the Content Security Policy, you can use the CSP browser test. This test attempts to load scripts and images from unknown (harmless) sources and tells you if this was suc­cess­ful.

In terms of the Content Security Policy and pre­vent­ing cross-site scripting, website operators should store all scripts in separate files instead of embedding them directly in the website’s source code. The CSP then works in a similar way to a whitelist: in the header, the sources, from which scripts and data can be loaded, are named. If an unknown script has slid un­de­tect­ed into the HTML code of the page and is now trying to load external data, the user’s browser needs to prohibit this. By default, the CSP blocks all scripts that can be found directly in the code (inline scripts). This protects both the website and the internet user as well as any sensitive data. Cross-site scripting is rel­a­tive­ly easy for cyber criminals to ma­nip­u­late. Almost every website has an input field i.e. comment function, search bar, or log-in field. Instead of simple text, it’s possible to also enter scripts. If the server is not ad­e­quate­ly secured, criminals can implement phishing in­ter­faces, bringing the entire website to a stand­still or gaining control of the user’s web browser using malicious software. CSP (or to be more precise: the cor­re­spond­ing header field) tells the web browser which sources it is permitted to load data from. If the policy is im­ple­ment­ed in the website’s code, at­tempt­ing to retrieve XSS-im­ple­ment­ed code will be met with an error message. The Content Security Policy also enables website operators to change many other settings. This can be done through these di­rec­tives:

  • base-uri: Restricts the URLs, which can be used in a website’s <base> element
  • child-src: Defines valid sources for web workers and nested browsing contexts loaded using elements such as <frame> and <iframe>
  • connect-src: Limits the sources that the site can connect to i.e. links
  • font-src: Defines valid font sources
  • form-action: Defines valid sources that can be used as an HTML <form> action
  • frame-ancestors: Defines valid sources for embedding the resource using <frame> and <iframes>
  • img-src: Defines valid images sources
  • media-src: Defines valid audio and video sources
  • object-src: Defines valid plugin sources
  • plugin-types: Defines valid plugins types
  • report-uri: Lets the browser know when a URL (to which reports are sent) violates security measures
  • script-src: Defines valid JavaScript sources
  • style-src: Defines valid stylesheet sources
  • upgrade-insecure-requests: Specifies that unsafe HTTP sites should be treated like HTTPS sites
  • sandbox: Moves the site in question to a sandbox where forms, pop-ups, and scripts are forbidden

These di­rec­tives only apply if they are ex­plic­it­ly set. Otherwise, they are open by default and therefore pose a security risk. However, this can be changed using default-src: you can set the default state of all di­rec­tives ending with -src. For example, instead of leaving it open, you can specify that only data from your own website may be loaded unless you have specified otherwise in the HTTP header of the in­di­vid­ual web page. In separate di­rec­tives, you add ad­di­tion­al sources. You can enter any number of di­rec­tives into the header field. If you want to include several di­rec­tives, separate them with semi­colons. In addition, you as the website operator must specify all sources within a directive. Multiple entries of the same directive with ad­di­tion­al sources are not permitted (such as in the following example):

script-src example1.local; script-src example2.local

In this case, only the first source is relevant, the second one is ignored by the client. Instead, you must record both sources in one directive:

script-src example1.local example2.local

If you do not need certain types of content for a page or the entire website, you can enter the value 'none' in the header – so you can specify that no sources may be loaded at all. You can also use the value 'self' – this means that the browser can only load content from the same source. Both values must always be quoted in single quotation marks, otherwise none and self will be in­ter­pret­ed as domains. There are different header options for defining a Content Security Policy:

  • Content-Security-Policy
  • X-Webkit-CSP
  • X-Content-Security-Policy

Not all browsers support every term. However, the W3C (the body re­spon­si­ble for defining web standards) suggests Content Security Policy. Therefore, all modern browsers have adapted to this security standard in the meantime (the other two versions are con­sid­ered obsolete). To make sure that you reach as many internet users as possible (even those with out-of-date browsers) with your CSP, it is advisable to include all header fields. If a cor­re­spond­ing web browser can’t handle the Content Security Policy header, it will simply ignore it and display the website without any problems – however, ad­di­tion­al pro­tec­tion isn’t given to the affected users. Usually, you will set HTTP headers across your entire domain. For sub-di­rec­to­ries, you can use the .htaccess file. You then use the CSP security standard to set special rules for in­di­vid­ual subpages. For example, if you have im­ple­ment­ed a social media button on one page, but not on the next one, it makes sense to only allow access to the external source on the first page. Sources can be entered as addresses, in their own way or as wildcards. The following entries are therefore allowed:

  • script-src example.com:443 – scripts are only allowed from this domain via HTTPS
  • script-src 'none' – scripts aren’t allowed to be loaded
  • script-src 'self' – scripts may be loaded from the same source as the current page, but not from sub­do­mains
  • script-src https: – scripts can be loaded from any domain as long as it starts with HTTPS
  • script-src example.com – scripts may be loaded from this domain
  • script-src *.example.com – scripts from this domain and all sub­do­mains are allowed
  • img-src data: – images can be loaded via data URLs

A Content Security Policy basically stip­u­lates that scripts may only be loaded from files, not directly from the website code. If you want to bypass this, you can use the command script-src 'unsafe-inline'. However, you should be aware that you are weakening security. The safety standard also prohibits the eval () feature. This command can be used to convert text into JavaScript code – but this can also pose a security risk. If you still need this function, you can re­ac­ti­vate it with script-src 'unsafe-eval'.

Tip

you can secure unsafe-inline using a detour. Hash values or nonce source close this vul­ner­a­bil­i­ty as much as possible.

If scripts are no longer allowed to appear directly in the code, you must create a separate file for each script. The script’s function is stored in a .js File. The website’s code only refers to these:

<script src='example.js'></script>

What the script does in the end is described in the example.js. You must also store style elements in separate stylesheets. If you want to implement an internet security policy as a website operator, it is not enough to simply insert the header. You also need to check and customize your website’s source code.

Note

do you want to know how secure your own website is? Mozilla has provided an easy-to-use test: Ob­ser­va­to­ry by Mozilla scans your website and gives you a grade after it’s completed, and tells you how to make your site safer

Content Security Policy: an example

As an example, we now show you how to implement a Content Security Policy header and explain what can be achieved with it.

  • Content-Security-Policy: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' fonts.google.com/; report-uri example.org/report.html"
  • X-Content-Security-Policy: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' fonts.google.com/; report-uri example.org/report.html"
  • X-WebKit-CSP: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' fonts.google.com/; report-uri example.org"

You can see that every CSP variant appears in the header so that as many different browsers as possible can be addressed. Inside each header name, the content is identical: sources are listed one after the other, and the di­rec­tives are separated by a semicolon. The syntax is always the same. In fact, only the name of the field changes, so you can easily duplicate the content.

First, we determine that, unless otherwise specified in a directive, data should not be loaded from just any source (default-src). This makes things a little bit safer. You should always define default-src first. This will prevent a po­ten­tial­ly forgotten directive from leaving a gap in your Content Security Policy.

Next, we define the source from which scripts can be loaded (script-src). In the example, we determine that the browser only loads scripts from the same source and from example.com including all sub­do­mains (you assign the wildcard using *). Fur­ther­more, we determine that clients are only allowed to load stylesheets from their own sources (style-src). Images are only allowed from their own source as a data URL (img-src). According to our Content Security Policy header, fonts may only be down­loaded from Google’s own sources. In the example, we specify a location to which no­ti­fi­ca­tions are sent if someone attempts to violate the security standard (report-uri).

You might have noticed that we haven’t included all the di­rec­tives in the header. This doesn’t cause any problems: In this case, we don’t need any more whitelists, and the default src turns off all other sources.

Tipp

several Content Security Policy gen­er­a­tors are available on the internet. With offers such as CSP Is Awesome or Report URI, you can create CSP header fields easily and reliably.

Go to Main Menu