Tuesday, January 1, 2013

Content Security Policy

I promised a post on Content Security Policy (CSP), so here it is. I recently gave a five minute talk about CSP and found it to be really well received. It is an exploit mitigation technology, created by the Mozilla Foundation, designed to minimize the surface area available for Cross-Site Scripting (XSS) attacks. I first learned about it at ArbSec, a monthly local security meeting that has beer. Jon Oberheide gave the presentation, referring to it as the "No NX Bit of the Web". NX bit (never execute) was created to mark pages in memory that should not contain executable code. So if an attacker was able to get code into a memory page that should only contain data, the NX bit will state to the CPU that it should not be executed. For some further reading: http://en.wikipedia.org/wiki/NX_bit

In the basic setup, Content Security Policy does the same in that a conforming website will remove inline JavaScript. Instead, that JavaScript will reside in a separate file and will be allowed to be executed in the policy. The server gives web browsers the policy through HTTP Headers:

Firefox and IE 10:
X-Content-Security-Policy

Google Chrome and Safari:
X-WebKit-CS

Official W3C Header (supported by Chrome version 25):
Content-Security-Policy

Once one of those headers is present, the web browser will disable inline JavaScript in these forms:
   - <script> code </script>
   - onclick
   - eval
   - setTimeout
   - setInterval

Source: http://en.wikipedia.org/wiki/Content_Security_Policy

When visiting http://ipsec.pl/node/1064 you can see the following sent back from the server:

HTTP/1.1 200 OK
Date: Mon, 31 Dec 2012 16:40:33 GMT
Server: Apache/2.2.16 (Debian)
Set-Cookie: SESS67bfceea1c6380ba6e0ac811371dccf6=vYrEGqQOJQnsIiNUBFC5djzTy-5; path=/; HttpOnly
Last-Modified: Mon, 31 Dec 2012 16:40:32 GMT
ETag: "29dc312167f2b7f026f157d5942f0e9d"
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Cache-Control: must-revalidate
Content-Encoding: gzip
X-Frame-Options: sameorigin
X-Content-Security-Policy: allow 'self'; script-src www.google.com www.readability.com; options inline-script; img-src *.creativecommons.org
X-XSS-Protection: 1; mode=block
Content-Type: text/html; charset=utf-8
Keep-Alive: 60
Content-Length: 7842

The key here is: X-Content-Security-Policy: allow 'self'; script-src www.google.com www.readability.com; options inline-script; img-src *.creativecommons.org

It is the policy pushed to your browser saying that JavaScript should only be loaded from google.com or readbility.com, no other places. To successfully perform a XSS attack in this scenario, the attacker would have to find a way to load the malicious JavaScript to google.com or readbility.com, greatly increasing the cost and effort required by the attacker.

For the full W3C CSP document: http://www.w3.org/TR/CSP

To utilize this technology, it is as simple as moving the JavaScript in your website to another file and configuring your web server to send the policy via the HTTP Headers. For Apache, allow the module:

LoadModule headers_module modules/mod_headers.so

And add this very simplistic policy to .htaccess (source: http://community.developer.authorize.net/t5/The-Authorize-Net-Developer-Blog/HTTP-Headers-to-Help-Secure-Your-Website/ba-p/8604):


# Don't allow any pages to be framed by my site or any others
# Defends against CSRF. Current only support by Firefox 4 but the
# other browser will add support soon.
Header set X-Frame-Options DENY

# Only allow JavaScript from the same domain to be run.
# Also, don't allow inline JavaScript to run.
Header set X-Content-Security-Policy "allow 'self';"

# Turns on IE 8 XSS prevention tools
Header set X-XSS-Protection "1; mode=block"

# Don't send out the Server header. This way no one knows what
# version of Apache and PHP I am using and try to exploit it.
Header unset Server