Tonight I added a new CSP – Content Security Policy to the demo.CiteIt.net website.
What are CSPs?
The basic idea behind CSPs (Content Security Policies) is that security can be improved if the webserver is configured to tell visitors’ web browsers to only accept files from approved sources. The policy can also specify specific types of actions that can take place, such as whether popups are allowed and whether the site can be accessed over unsecured HTTP (rather than HTTPS).
One of the benefits of applying a CSP to a website is that a public user adding a new sample post would be prevented from embedding a malicious script from a remote source. Or more accurately, web visitors who view a page with an embedded malicious script would be instructed by the webserver not to load this remote script, even if it were successfully injected into the page.
Allowed:
<script src="https://demo.citeit.net/my/script.js" />
Forbidden:
<script src="https://evil.attacker.com/bad/script.js" />
Because my CSP defines a set of rules that only allows scripts from self, the web server will instruct the browser not to load the malicious remote script.
Apache .htaccess Configuration
These instructions are set by configuring the web server, which in my case is Apache.
Here’s some basic .htaccess code for Apache:
<IfModule mod_headers.c>
Header Content-Security-Policy-Report-Only:
default-src 'self';
script-src 'self' ajax.googleapis.com;
style-src 'self';
img-src 'self';
font-src fonts.googleapis.com, fonts.gstatic.com;
connect-src 'self'; media-src www.youtube.com;
object-src 'none';
prefetch-src read.citeit.net, fonts.googleapis.com, fonts.gstatic.com;
child-src 'self' www.youtube.com;
frame-src 'self' www.youtube.com; worker-src 'none';
frame-ancestors 'self';
form-action 'self';
upgrade-insecure-requests;
block-all-mixed-content;
sandbox allow-forms allow-same-origin allow-scripts allow-popups;
reflected-xss block; base-uri 'self';
manifest-src 'none';
report-uri https://demociteitnet.report-uri.com/r/d/csp/enforce
Header set X-Content-Type-Options nosniff
Header set X-Frame-Options DENY
</IfModule>
Tightening up Permissions Further:
It is possible to tighten up security further by having the javascript only run a script whose content matches a hash. You see this often with CDNs:
<script src="https://code.jquery.com/jquery-2.1.4.min.js"
integrity="sha384-R4/ztc4ZlRqWjqIuvf6RX5yb/v90qNGx6fS48N0tRxiGkqveZETq72KgDVJCp2TC"
crossorigin="anonymous"></script>
This technique allows the website author to include a remote script from a CDN without worrying that the contents of the script (in this case jQuery) will change. Adding the integrity check prevents the visitor from loading a malicious copy of the script, should the jQuery website get hacked.