1## Using Content Security Policy (CSP) 2 3### What is it? 4 5Modern browsers have recently implemented a new feature providing 6a sort of "selinux for your web page". If the server sends some 7new headers describing the security policy for the content, then 8the browser strictly enforces it. 9 10### Why would we want to do that? 11 12Scripting on webpages is pretty universal, sometimes the scripts 13come from third parties, and sometimes attackers find a way to 14inject scripts into the DOM, eg, through scripts in content. 15 16CSP lets the origin server define what is legitimate for the page it 17served and everything else is denied. 18 19The CSP for warmcat.com and libwebsockets.org looks like this, 20I removed a handful of whitelisted image sources like travis 21status etc for clarity... 22 23``` 24"content-security-policy": "default-src 'none'; img-src 'self' data:; script-src 'self'; font-src 'self'; style-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'none';", 25"x-content-type-options": "nosniff", 26"x-xss-protection": "1; mode=block", 27"x-frame-options": "deny", 28"referrer-policy": "no-referrer" 29``` 30 31The result of this is the browser won't let the site content be iframed, and it 32will reject any inline styles or inline scripts. Fonts, css, ajax, ws and 33images are only allowed to come from 'self', ie, the server that served the 34page. You may inject your script, or deceptive styles: it won't run or be shown. 35 36Because inline scripts are banned, the usual methods for XSS are dead; 37the attacker can't even load js from another server. So these rules 38provide a very significant increase in client security. 39 40### Implications of strict CSP 41 42Halfhearted CSP isn't worth much. The only useful approach is to start 43with `default-src 'none'` which disables everything, and then whitelist the 44minimum needed for the pages to operate. 45 46"Minimum needed for the pages to operate" doesn't mean defeat the protections 47necessary so everything in the HTML can stay the same... it means adapt the 48pages to want the minimum and then enable the minimum. 49 50The main point is segregation of styles and script away from the content, in 51files referenced in the document `<head>` section, along these lines: 52 53``` 54<head> 55 <meta charset=utf-8 http-equiv="Content-Language" content="en"/> 56 <link rel="stylesheet" type="text/css" href="test.css"/> 57 <script type='text/javascript' src="/lws-common.js"></script> 58 <script type='text/javascript' src='test.js'></script> 59 <title>Minimal Websocket test app</title> 60</head> 61``` 62 63#### Inline styles must die 64 65All styling must go in one or more `.css` file(s) best served by the same 66server... while you can whitelist other sources in the CSP if you have to, 67unless you control that server as well, you are allowing whoever gains 68access to that server access to your users. 69 70Inline styles are no longer allowed (eg, "style='font-size:120%'" in the 71HTML)... they must be replaced by reference to one or more CSS class, which 72in this case includes "font-size:120%". This has always been the best 73practice anyway, and your pages will be cleaner and more maintainable. 74 75#### Inline scripts must die 76 77Inline scripts need to be placed in a `.js` file and loaded in the page head 78section, again it should only be from the server that provided the page. 79 80Then, any kind of inline script, yours or injected or whatever, will be 81completely rejected by the browser. 82 83#### onXXX must be replaced by eventListener 84 85Inline `onclick()` etc are kinds of inline scripting and are banned. 86 87Modern browsers have offered a different system called ["EventListener" for 88a while](https://developer.mozilla.org/en-US/docs/Web/API/EventListener) 89which allows binding of events to DOM elements in JS. 90 91A bunch of different named events are possible to listen on, commonly the 92`.js` file will ask for one or both of 93 94``` 95window.addEventListener("load", function() { 96... 97}, false); 98 99document.addEventListener("DOMContentLoaded", function() { 100... 101}, false); 102``` 103 104These give the JS a way to trigger when either everything on the page has 105been "loaded" or the DOM has been populated from the initial HTML. These 106can set up other event listeners on the DOM objects and aftwards the 107events will drive what happens on the page from user interaction and / or 108timers etc. 109 110If you have `onclick` in your HTML today, you would replace it with an id 111for the HTML element, then eg in the DOMContentLoaded event listener, 112apply 113 114``` 115 document.getElementById("my-id").addEventListener("click", function() { 116 ... 117 }, false); 118``` 119 120ie the .js file becomes the only place with the "business logic" of the 121elements mentioned in the HTML, applied at runtime. 122 123#### Do you really need external sources? 124 125Do your scripts and fonts really need to come from external sources? 126If your caching policy is liberal, they are not actually that expensive 127to serve once and then the user is using his local copy for the next 128days. 129 130Some external sources are marked as anti-privacy in modern browsers, meaning 131they track your users, in turn meaning if your site refers to them, you 132will lose your green padlock in the browser. If the content license allows 133it, hosting them on "self", ie, the same server that provided the HTML, 134will remove that problem. 135 136Bringing in scripts from external sources is actually quite scary from the 137security perspective. If someone hacks the `ajax.googleapis.com` site to serve 138a hostile, modified jquery, half the Internet will instantly 139become malicious. However if you serve it yourself, unless your server 140was specifically targeted you know it will continue to serve what you 141expect. 142 143Since these scripts are usually sent with cache control headers for local 144caching duration of 1 year, the cost of serving them yourself under the same 145conditions is small but your susceptibility to attack is reduced to only taking 146care of your own server. And there is a privacy benefit that google is not 147informed of your users' IPs and activities on your site. 148 149