2. Who am I?
• A developer at Kisko Labs
• In my free 8me I work on too many side projects
• piranhas.co — a book price comparison site and app
• Beer Styles — an iOS app for browsing beer style guidelines
• TLS.caresoon!
— an SSL/TLS cer8ficate monitoring service
• and I also brew beer
3. Kisko Labs
We build and launch tools on the web
Are you a Ruby or frontend developer? We're hiring
5. Content Security Policy is an added
layer of security that helps to detect
and mi3gate certain types of
a5acks, including Cross Site
Scrip3ng (XSS) and data injec3on
a5acks.
— MDN
6. Content Security Policy: a header
which tells the browser where
resources (scripts, stylesheets, fonts,
etc) can be loaded from.
— Me
7. Supported by all major browsers,
even Internet Explorer (kind of)
8.
9. CSP: Why?
• Reduces the poten.al surface area for a3acks or malicious
injec.on of scripts
• Prevents malicious browser extensions and malware from
inser.ng crap into your pages.
• For example, the CSP on Piranhas.co has stopped some shady
browser extensions from injec.ng ads?
onto the page.
13. I don't know what this is, but I know that I don't want it on my site!
14. CSP Direc*ves
Content Security Policies allow quite fine grained control over what
can be loaded from where.
For example, you can allow scripts from a domain but not images
(or vice versa).
Or, for example, if you allow users to upload images, but not
scripts, you can segregate user uploads to a specific host (“allow
images from uploads.example.com but nothing else”).
15. Available direc,ves
• default-src: Define loading policy for all resources type in case of
a resource type dedicated direc5ve is not defined (fallback),
• script-src: Define which scripts the protected resource can
execute,
• object-src: Define from where the protected resource can load
plugins,
• style-src: Define which styles (CSS) the user applies to the
protected resource,
16. • img-src: Define from where the protected resource can load
images,
• media-src: Define from where the protected resource can load
video and audio,
• frame-src: Define from where the protected resource can embed
frames,
• font-src: Define from where the protected resource can load
fonts,
17. • connect-src: Define which URIs the protected resource can load
using script interfaces,
• form-ac-on: Define which URIs can be used as the ac;on of
HTML form elements,
• sandbox: Specifies an HTML sandbox policy that the user agent
applies to the protected resource,
• script-nonce: Define script execu;on by requiring the presence
of the specified nonce on script elements,
18. • plugin-types: Define the set of plugins that can be invoked by
the protected resource by limi:ng the types of resources that
can be embedded,
• reflected-xss: Instructs a user agent to ac:vate or deac:vate any
heuris:cs used to filter or block reflected cross-site scrip:ng
a?acks, equivalent to the effects of the non-standard X-XSS-
Protec:on header,
• report-uri: Specifies a URI to which the user agent sends reports
about policy viola:on
19. Adding a CSP header to a long
standing site can be … tricky
23. CSP example (simplified alterna3ve)
Content-Security-Policy: default-src 'self';
Allow all sources, but disallow unsafe inline assets (for example
scripts and styles).
24. 'unsafe-inline' vs “safe inline”
• By default inline scripts are blocked
• You can either
• add 'unsafe-inline' to your CSP (in which case you're
back where your started)
• or use inline scripts with a nonce (more on this later)
25. In cryptography, a nonce is an
arbitrary number that may only be
used once.
— Wikipedia
26. You specify the nonce in the CSP header:
Content-Security-Policy: ...
script-src 'nonce-/jRAxuLJsDXAxqhNBB7gg7h55KETtDQBXe4ZL+xIXwI=' ...;
and in your <script> (or <style>) tag:
<script nonce="/jRAxuLJsDXAxqhNBB7gg7h55KETtDQBXe4ZL+xIXwI=">
console.log("Hello World")
</script>
The browser will allow each nonce to be used only once…
28. Secure Headers
A Rack middleware gem from Twi2er which adds support for more
security headers than are available by default in Rails.
• h#ps://github.com/twi#er/secureheaders
• h#ps://rubygems.org/gems/secure_headers
Makes it easier to use CSP headers (and it also handles other
security headers)
29. Secure Headers
It lets you define an app-wide CSP that you can override or append
to at a controller or ac9on level.
Don't just add it though. Look through the configura6on and
understand what it's doing. You might want to disable some of the
op6ons.
31. Secure Headers: nonces
It also includes support for safe inline styles and scripts using
nonces.
For example:
<%= nonced_javascript_tag do %>
console.log("nonced!");
<% end %>
32. Secure Headers: nonces
Generates this HTML:
<script nonce="/jRAxuLJsDXAxqhNBB7gg7h55KETtDQBXe4ZL+xIXwI=">
console.log("nonced!")
</script>
And adds this to the CSP header:
Content-Security-Policy: ...
script-src 'nonce-/jRAxuLJsDXAxqhNBB7gg7h55KETtDQBXe4ZL+xIXwI=' ...;
33. Secure Headers: minimal configura3on
# config/initializers/secure_headers.rb
SecureHeaders::Configuration.default do |config|
config.csp = {
default_src: %w(*),
upgrade_insecure_requests: Rails.env.production?, # see https://www.w3.org/TR/upgrade-insecure-requests/
report_uri: %w(https://x.report-uri.io/r/default/csp/enforce)
}
config.hpkp = SecureHeaders::OPT_OUT
end
Or you might want to use 'self' instead of *
34. Secure Headers
Rails also sets some of the same security headers, but Secure
Headers has code to override those with its own configura;on.
=> Secure Headers knows how to play nice with Rails
35. => Secure Headers knows how to play nice with Rails
isolate_namespace SecureHeaders if defined? isolate_namespace # rails 3.0
conflicting_headers = ['X-Frame-Options', 'X-XSS-Protection',
'X-Permitted-Cross-Domain-Policies', 'X-Download-Options',
'X-Content-Type-Options', 'Strict-Transport-Security',
'Content-Security-Policy', 'Content-Security-Policy-Report-Only',
'Public-Key-Pins', 'Public-Key-Pins-Report-Only', 'Referrer-Policy']
# ...
conflicting_headers.each do |header|
Rails.application.config.action_dispatch.default_headers.delete(header)
end
h"ps://github.com/twi"er/secureheaders/blob/v3.4.1/lib/
secure_headers/rail;e.rb
37. CSP pro-)ps
Start by using the Content-Security-Policy-Report-Only
header to test and tweak your CSP header in the wild.
Content-Security-Policy-Report-Only:
default-src *,
report-uri https://x.report-uri.io/r/default/csp/enforce;;
Deploy the Report Only header for a few days before star1ng to
enforce it.
38. CSP pro-)ps
• New projects
• Enforce the CSP from the beginning
• Report viola<ons from your staging or produc<on environment
• Old projects
• Add a CSP with all the sources you think you need
• Deploy it as Report Only, leave it for a week or two to uncover anything you might have forgoEen
about
• Deploy the enforced policy once you've accounted for all the viola<ons
• Both
• When making changes, you may wish to first test them with the Report Only header (depending on the
change)
42. Summary
• Rails defaults are pre/y good, but can be (fairly easily) be 9ghtened
• Use a Content Security Policy, if only to prevent ad/malware injec9on by
compromised browsers
• The more strict the CSP is, the fewer chances there are for third par9es to mess
with your site
• Use the Secure Headers gem to manage the CSP policy and other security headers
• It requires more thought than the Rails defaults, but I think it's worth it
• Excep&on to all of the above: If you're working on your first Rails app, you
probably shouldn't add this complexity.