$30 off During Our Annual Pro Sale. View Details »

Integrity protection for third-party JavaScript

Integrity protection for third-party JavaScript

Modern web applications depend on a lot of auxiliary scripts which are often hosted on third-party CDNs. Should an attacker be able to tamper with the files hosted on such a CDN, millions of sites could be compromised. Web developers need a way to guarantee the integrity of scripts hosted elsewhere.

This is the motivation behind a new addition to the web platform being introduced by the W3C: sub-resource integrity (http://www.w3.org/TR/SRI/). Both Firefox and Chrome have initial implementations of this new specification and a few early adopters such as Github are currently evaluating this feature.

Francois Marier

June 04, 2015
Tweet

More Decks by Francois Marier

Other Decks in Programming

Transcript

  1. eapis.com/ajax/libs/jquery/1.8.<br/>0/jquery.min.js” integrity=”typ<br/>e:text/javascript sha512-AODL7i<br/>dgffQeNsYdTzut09nz9AINcjhj4jHD7<br/>2HcLirsidbC8tz+dof7gceOCQD8Wske<br/>uRFfJ9CsgZTHlMiOYg==”>
    Integrity protection for
    3rd-party JavaScript
    François Marier @fmarier
    mozilla

    View Slide

  2. Firefox
    Security & Privacy

    View Slide

  3. Web Platform

    View Slide

  4. Web Platform

    View Slide

  5. Content Security Policy
    aka CSP

    View Slide

  6. Content Security Policy
    aka CSP
    mechanism for preventing XSS

    View Slide

  7. telling the browser what external
    content is allowed to load

    View Slide

  8. what does CSP look like?

    View Slide

  9. $ curl --head https://mega.nz
    HTTP/1.1 200 OK
    Content-Type: text/html
    Content-Length: 1989
    Content-Security-Policy:
    default-src 'self' *.mega.co.nz *.mega.nz
    http://*.mega.co.nz http://*.mega.nz;
    script-src 'self' mega.co.nz mega.nz data:
    blob:;
    style-src 'self' 'unsafe-inline' *.mega.nz
    *.mega.co.nz data: blob:;
    frame-src 'self' mega:;
    img-src 'self' *.mega.co.nz *.mega.nz data:

    View Slide

  10. Hi you<br/>alert('p0wned');<br/>!
    Tweet!
    What's on your mind?

    View Slide

  11. without CSP

    View Slide

  12. Hi you!
    John Doe - just moments ago
    p0wned
    Ok

    View Slide

  13. with CSP

    View Slide

  14. Hi you!
    John Doe - just moments ago

    View Slide

  15. Content-Security-Policy:
    script-src 'self'
    https://cdn.example.com

    View Slide

  16. inline scripts are blocked unless
    unsafe-inline is specified

    View Slide

  17. script-src
    object-src
    style-src
    img-src
    media-src
    frame-src
    font-src
    connect-src

    View Slide

  18. $ curl --head https://twitter.com
    HTTP/1.1 200 OK
    content-length: 58347
    content-security-policy: …
    report-uri https://twitter.com/csp_report
    violation reports:

    View Slide

  19. "csp-report": {
    "document-uri":
    "http://example.org/page.html",
    "referrer":
    "http://evil.example.com/haxor.html",
    "blocked-uri":
    "http://evil.example.com/image.png",
    "violated-directive": "default-src 'self'",
    "effective-directive": "img-src",
    "original-policy":
    "default-src 'self';
    report-uri http://example.org/..."
    }

    View Slide

  20. View Slide

  21. support for inline scripts
    Content-Security-Policy:
    script-src 'sha256-YWIzOW...'

    View Slide

  22. View Slide

  23. Strict Transport Security
    aka HSTS

    View Slide

  24. Strict Transport Security
    aka HSTS
    mechanism for preventing
    HTTPS to HTTP downgrades

    View Slide

  25. telling the browser that your site
    should never be reached over HTTP

    View Slide

  26. View Slide

  27. GET bank.com.au 301

    GET https://bank.com.au 200

    no HSTS, no sslstrip

    View Slide

  28. GET bank.com.au → 200
    no HSTS, with sslstrip

    View Slide

  29. what does HSTS look like?

    View Slide

  30. $ curl -i https://login.xero.com
    HTTP/1.1 200 OK
    Cache-Control: private
    Content-Type: text/html; charset=utf-8
    Strict-Transport-Security: max-age=31536000
    X-Frame-Options: SAMEORIGIN

    View Slide

  31. with HSTS, with sslstrip
    GET https://bank.com.au 200

    View Slide

  32. silent client-side redirects
    HTTP → HTTPS

    View Slide

  33. no HTTP traffic for
    sslstrip to tamper with

    View Slide

  34. except for the very
    first connection

    View Slide

  35. https://hstspreload.appspot.com/

    View Slide

  36. pop quiz!
    how many .au sites are
    on the preload list?

    View Slide

  37. aurainfosec.com.au
    bcm.com.au
    bigbrownpromotions.com.au
    comssa.org.au
    data.qld.gov.au
    dreamsforabetterworld.com.au
    dylanscott.com.au
    fatzebra.com.au
    freethought.org.au
    netrider.net.au
    publications.qld.gov.au
    technotonic.com.au
    thomastimepieces.com.au
    tracktivity.com.au
    tradingcentre.com.au
    webandwords.com.au
    16

    View Slide

  38. aurainfosec.com.au
    bcm.com.au
    bigbrownpromotions.com.au
    comssa.org.au
    data.qld.gov.au
    dreamsforabetterworld.com.au
    dylanscott.com.au
    fatzebra.com.au
    freethought.org.au
    netrider.net.au
    publications.qld.gov.au
    technotonic.com.au
    thomastimepieces.com.au
    tracktivity.com.au
    tradingcentre.com.au
    webandwords.com.au

    View Slide

  39. View Slide

  40. View Slide

  41. View Slide

  42. View Slide

  43. 2015?

    View Slide

  44. View Slide

  45. View Slide

  46. View Slide

  47. View Slide

  48. https://ajax.googleapis.com
    /ajax/libs/jquery/1.8.0/
    jquery.min.js

    View Slide

  49. how common is this?

    View Slide

  50. View Slide

  51. what would happen if that
    server were compromised?

    View Slide

  52. View Slide

  53. Bad Things™
    steal sessions
    leak confidential data
    redirect to phishing sites
    enlist DDoS zombies

    View Slide

  54. simple solution

    View Slide

  55. instead of this:
    src=”https://ajax.googleapis.com...”>

    View Slide

  56. src=”https://ajax.googleapis.com...”
    integrity=”sha256-1z4uG/+cVbhShP...”>
    do this:

    View Slide

  57. You owe me $10.00.
    f4243c12541be6f79c73e539c426e07a
    f2f6c4ef8794894f4903aee54542586d

    View Slide

  58. You owe me $1000.
    1ebd7a8d15a6dab743f0c4d147f731bc
    fc6b74752afe43afa5389ba8830a2215

    View Slide

  59. guarantee:
    script won't change
    or it'll be blocked

    View Slide

  60. limitation:
    won't work for scripts
    that change all the time

    View Slide

  61. 3 types of scripts

    View Slide

  62. dynamically-generated script:
    not a good fit for SRI
    I

    View Slide

  63. immutable scripts:
    perfect for SRI
    II

    View Slide

  64. https://ajax.googleapis.com
    /ajax/libs/jquery/1.8.0/
    jquery.min.js

    View Slide

  65. what about your own scripts?
    (they change, but you're
    the one changing them)

    View Slide

  66. III
    scripts under your control:
    good fit for SRI

    View Slide

  67. can usually add the hashing to
    your static resource pipeline

    View Slide

  68. #!/bin/sh
    cat src/*.js > bundle.js
    HASH=`sha256sum bundle.js |cut -f1 -d' '`
    mv bundle.js public/bundle-${HASH}.js

    View Slide

  69. public/bundle-c2498bc358....js
    Cache-Control: max-age=∞

    View Slide

  70. <br/><script src=”app.js”><br/><script src=”menu.js”><br/>

    View Slide

  71. <br/>

    View Slide

  72. integrity=”sha256-c2498bc...”><br/>

    View Slide

  73. what else?

    View Slide

  74. integrity=”
    sha256-9Cm9ekBvKrtQ0A...
    “ sha256-rKSr3LcX+EkeM=...
    sha256-1z4uG/+cVbhShP...
    sha384-RqG7UC/QK2TVRa...
    sha512-AODL7idgffQeNs...

    View Slide

  75. integrity=”
    sha256-9Cm9ekBvKrtQ0A...
    sha256-rKSr3LcX+EkeM=...
    sha256-1z4uG/+cVbhShP...
    “ sha384-RqG7UC/QK2TVRa...
    sha512-AODL7idgffQeNs...

    View Slide

  76. integrity=”
    sha256-9Cm9ekBvKrtQ0A...
    sha256-rKSr3LcX+EkeM=...
    sha256-1z4uG/+cVbhShP...
    sha384-RqG7UC/QK2TVRa...
    sha512-AODL7idgffQeNs...

    View Slide

  77. what about cross-origin requests?

    View Slide

  78. “a web browser permits scripts contained in a first
    web page to access data in a second web page,
    but only if both web pages have the same origin”
    same-origin policy

    View Slide

  79. example.com/index.html

    View Slide

  80. example.com/index.html
    example.com/data.js:
    var secret = 42;

    View Slide

  81. example.com/index.html
    example.com/data.js:
    var secret = 42;
    evil.net/widget.js:
    exfiltrate(secret);

    View Slide

  82. example.com/index.html
    example.com/data.js:
    var secret = 42;
    evil.net/widget.js:
    exfiltrate(secret);

    View Slide

  83. View Slide

  84. on the server:
    Access-Control-Allow-Origin: *

    View Slide

  85. on the server:
    Access-Control-Allow-Origin: *
    on the client:
    crossorigin=”anonymous”

    View Slide

  86. src=”https://ajax.googleapis.com...”
    integrity=”sha256-1z4uG/+cVbhShP...”
    crossorigin=”anonymous”>
    complete example:

    View Slide

  87. href="style.css"
    integrity="sha256-PgMdguwx/O..."
    crossorigin=”anonymous”>
    complete example:

    View Slide

  88. cat file.js
    | openssl dgst -sha256 -binary
    | openssl enc -base64 -A

    View Slide

  89. SRIhash.org

    View Slide

  90. View Slide

  91. status?

    View Slide

  92. spec is being finalized

    View Slide

  93. (initial implementations)

    View Slide

  94. demo

    View Slide



  95. Bug 992096 - Implement SRI
    href="http://localhost/francois/sri/style.css"
    integrity="
    sha256-PgMdguwx/O1ZJKqtGj54HIScoj0UEDV4ti5tLuc4DvA="
    crossorigin="anonymous">


    This should be red if the hash matches!


    View Slide

  96. h1 {
    color: red;
    }

    View Slide

  97. View Slide

  98. View Slide



  99. Bug 992096 - Implement SRI
    href="http://localhost/francois/sri/style.css"
    integrity="
    sha256-bogus"
    crossorigin="anonymous">


    This should be red if the hash matches!


    View Slide

  100. View Slide

  101. View Slide

  102. Questions?
    feedback:
    [email protected]
    mozilla.dev.security
    [email protected]
    © 2015 François Marier
    This work is licensed under a
    Creative Commons Attribution-ShareAlike 4.0 License.

    View Slide

  103. photo credits:
    bank notes: https://www.flickr.com/photos/epsos/8463683689
    web devs: https://www.flickr.com/photos/mbiddulph/238171366
    explosion: https://www.flickr.com/photos/-cavin-/2313239884/

    View Slide