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