Security/CSP/Deploying

From MozillaWiki
Jump to navigation Jump to search

In this article, we'll recommend steps that can be taken to modify a web site so that it will support CSP base restrictions. We will also explain how to craft a CSP policy for a site that will provide a maximum amount of protection.

Supporting CSP base restrictions

While restricting content loads by source may help mitigate attacks, there are base restrictions needed to properly avoid more complex XSS script injection attacks. Let's take a look at all of the base restrictions employed by CSP and see how equivalent functionality can be obtained through other techniques.

Until a site has been converted to support these base restrictions, the "inline" and "eval" keywords in the script-src directive can be used to disable them. The effort required to support the base restrictions will vary by site, but we'll provide some guidelines on how to convert sites, one restriction at a time.

Removing Inline Scripts

You can skip this part by adding the inline keyword to the script-src directive in your site's CSP policy definition.

Inline scripts are more easily injected into a site than their externally sourced counterparts. This is a side effect of mixing code and content.

<script> tags with text child nodes

The Problem
Inline scripting is the most popular vector for XSS, and a site that is vulnerable to any content injection might be coerced into displaying an inline script node. Since CSP rules can't block this (like they can block the script file load from a third party site), it must be disabled.
General Solution
To prevent your inline scripts from being blocked, there are two techniques that can be employed.
  1. Move all the inline scripts into one external script file, then reference the file with a <script src='thefile.js'> tag in the document's head.
  2. Move each inline script block into an external script file, and reference them individually from script blocks.

The most straightforward conversion technique is (2), but will lead to more HTTP requests being sent. Both techniques will be discussed here.

Conversion Steps
If the inline script blocks are context-insensitive (i.e., don't require document.write and just provide some functionality), they can easily be moved into a page-level external file. If they require context, they might need to each be stored in a separate file.

Approach (1): moving scripts into a single external file

  1. Collect the text content of each script block
  2. Concatenate the contents into a new file "moved.js"
  3. Replace the first inline script tag with <script src='moved.js'></script>. Alternatively, this can be placed in the head element of the document.

Approach (2): individual external files

  1. Generate a unique ID for each script block
  2. Create a JS file with the script block's contents, named with the given unique ID
  3. Replace the inline script block with <script src='[unique-id].js'></script>

Approach (1+2): providing context to bits of script

A combination of the two techniques can be used to minimize the number of requests while still providing a bit of context.

  1. Each inline code block is assigned a unique ID.
  2. All the code blocks are placed in a single file.
  3. The file must be loaded at the end of the document, right before the closing body tag.
  4. Dummy HTML elements are inserted where the inline script blocks were, labeled with the unique IDs. This allows the code to find where it "used to be".

javascript: URIs

The Problem
URIs that use the javascript scheme are another popular method to inject and run arbitrary script on a web page. Like inline script, these can be injected into html tags causing arbitrary script execution, so CSP disables javascript: URIs.
General Solution
If javascript: URIs are used in your web site, they can often be converted to script-initiated code. Common uses of such URIs are:
  • TODO: list cases
Conversion Steps
  • TODO: on case-by-case basis

Event handling attributes in HTML tags

The Problem
There are many HTML event handling attributes (on*) that can contain strings to be evaluated as script.
General Solution
Conversion Steps

Removing "eval()"-like features

You can skip this part by adding the eval keyword to the script-src directive in your site's CSP policy definition.

Code generated on the fly can accidentally (or intentionally) contain user-specified content; any strings converted into script code during the run-time of a web application has the potential to be augmented and abused by an attacker. As a result, these must be removed from a site.

eval()

The Problem
General Solution
Conversion Steps

setTimeout()

The Problem
General Solution
Conversion Steps

setInterval()

The Problem
General Solution
Conversion Steps

new Function()

The Problem
General Solution
Conversion Steps

Often Misused Feature Clean up

  • data: URIs
  • XBL bindings


Writing an effective policy

Example: Media and Object

<video controls="controls" width="320" height="240">
  <source src="/media/ogg/bfw-trailer-320x240.ogv" type="video/ogg">
  <object type="application/x-java-applet" width="320" height="240">
    <param name="archive" value="http://theora.org/cortado.jar">
    <param name="code" value="com.fluendo.player.Cortado.class">
    <param name="url" value="/media/ogg/bfw-trailer-320x240.ogv">
    <param name="autoPlay" value="false">
  </object>
</video>

The minimal policy for a page containing only this code:

allow none; media-src self; object-src self http://theora.org;