A primer on Content Security Policy

A primer on Content Security Policy

Content Security Policy (CSP) is as a security concept aiming to prevent XSS and other forms of browser–based attacks right where they happen — in the browser. CSP has been around for a little while but it’s only now that browser vendors are closing in on implementing most of the W3C specification.

This talk will take a look at what CSP is, why it matters and how to use it with Ruby–based web applications.

References: https://gist.github.com/polarblau/9efa552df23b3cd8f967

8c367856dfeee6972848cc82c79c0638?s=128

Florian Plank

October 02, 2014
Tweet

Transcript

  1. CSP Content Security Policy

  2. DISCLAIMER

  3. () { :; };

  4. THE ISSUE AT HAND

  5. XSS — and other browser–based attacks

  6. Same origin policy

  7. Same origin policy http://foo.com http://bar.com

  8. XSS

  9. Persisted XSS

  10. Persisted XSS User A Server

  11. <IMG SRC=javascript:alert("XSS")>

  12. Persisted XSS User A Server User B

  13. None
  14. User B User B User B Persisted XSS User A

    Server User B
  15. Persisted XSS User A Server User B

  16. Reflected XSS

  17. <%= params[:user].html_safe %>

  18. SESSION HIJACKING CONTENT SPOOFING …

  19. <img src="..." onerror=alert(document.cookie);>

  20. None
  21. None
  22. THE ROOT OF THE PROBLEM?

  23. The user

  24. The browser

  25. THE SOLUTION

  26. MOAR REGEX!!1!

  27. <STYLE>li {list-style-image: ↵ url(“javascript:alert(‘XSS')");} ↵ </STYLE><UL><LI>XSS</br> ! <IMG SRC="jav&#x0A;ascript:alert('XSS');"> !

    <IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114; ↵ &#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114; ↵ &#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;> ! <IMG SRC=/ ↵ onerror=“alert(String.fromCharCode(88,83,83))”> ↵ </img>
  28. — OWASP XSS Prevention Rules

  29. Never Insert Untrusted Data Except in Allowed Locations 1

  30. HTML Escape Before Inserting Untrusted Data into HTML Element Content

    2
  31. Attribute Escape Before Inserting Untrusted Data into HTML Common Attributes

    3
  32. JavaScript Escape Before Inserting Untrusted Data into JavaScript Data Values

    4
  33. HTML escape JSON values in an HTML context and read

    the data with JSON.parse 4.1
  34. JSON entity encoding 4.1.1

  35. HTML entity encoding 4.1.2

  36. CSS Escape And Strictly Validate Before Inserting Untrusted Data into

    HTML Style Property Values 5
  37. URL Escape Before Inserting Untrusted Data into HTML URL Parameter

    Values 6
  38. Sanitize HTML Markup with a Library Designed for the Job

    7
  39. Prevent DOM-based XSS 8

  40. None
  41. MOAR REGEX!!1!

  42. Bonus Rules!

  43. Use HTTPOnly cookie flag A

  44. Implement Content Security Policy B

  45. Content Security Policy

  46. None
  47. None
  48. None
  49. None
  50. None
  51. WHAT DOES IT DO?

  52. Same origin policy

  53. What can be loaded and embedded, and from where?

  54. Which origins can be connected to?

  55. Which scripts can be executed and in which context?

  56. HOW DOES IT WORK?

  57. Response header

  58. Content-Security-Policy: script-src 'self' Header name X-WebKit-CSP X-Content-Security-Policy IE > 9

    < ? Webkit < 6.1
  59. Content-Security-Policy: script-src 'self' Directive

  60. Content-Security-Policy: script-src 'self' Attribute (source)

  61. Content-Security-Policy: [DIRECTIVE A]; [DIRECTIVE B]

  62. Content-Security-Policy: script-src 'self' ↵ https://apis.google.com Multiple sources

  63. class CSP def initialize(app, options={}) @app = app end def

    call(env) status, headers, body = @app.call(env) response = Rack::Response.new body, status, headers response['Content-Security-Policy'] = "script-src 'self'" response.finish end end
  64. Directives

  65. default-src ! Default source for all directives

  66. default-src ! Default source for all directives

  67. connect-src ! Connections via XHR, WebSockets and EventSource

  68. font-src ! Origins of web fonts

  69. frame-src ! Origins embeddable via frames

  70. img-src ! Origins of images

  71. media-src ! Origins for audio and video

  72. object-src ! Origins of Flash and other plugins

  73. style-src ! Origins of stylesheets

  74. Sandboxing

  75. sandbox ! Load page as loaded into iframe with “sandbox”

    attribute
  76. Sources

  77. 'none' ! Match nothing

  78. None
  79. 'self' ! Only current origin

  80. http://example.com:80 ! Servers

  81. http: *://example.com:* ! Wildcards

  82. Script execution (Source)

  83. 'unsafe-inline' ! Execute inline javascript

  84. 'unsafe-eval' ! Eval is evil

  85. setTimeout("alert('XSS')", 10);

  86. var xss = new Function("alert('XSS');"); xss();

  87. Reporting

  88. report-uri ! Endpoint for POST requests with JSON payload

  89. Content-Security-Policy: report-uri /csp_report

  90. { "csp-report": { "document-uri": "...", "referrer": "...", "blocked-uri": "...", "violated-directive":

    "...", "original-policy": "...", } }
  91. class CSPReporter def call(env) report_data = JSON.parse(env['rack.input'].read) report_data = report_data['csp-report']

    if report_data Logger.new(‘logs/csp_report.log’).warn( format_report(report_data) ) end end private def format_report(data) # ... end end
  92. map '/csp_report' do run CSPReporter.new end

  93. Reporting ONLY

  94. Content-Security-Policy-Report-Only: […]

  95. CAN I USE IT?

  96. http://caniuse.com Can I use it?

  97. RUBY GEMS

  98. twitter/secureheaders ! p0deje/content-security-policy

  99. default: &default scope: "*" directives: - scripts: self https://google.com !

    report: <<: *default directives: - report_uri: /csp_report
  100. None
  101. THANKS! @polarblau