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