There’s no party like 3rd party!

How to handle dependencies securely

Frederic Hemberger
GDG DevFest 2016

Third party code

Know the sources
Limit the sources

npm

Keep dependencies up to date

2014: On Alexaʼs Top 100,000 websites,
75% use a jQuery version older than 2½ years.
On 35% itʼs even older than 5 years.

2016: Scanning the domains of the Fortune 500 companies,
83% contained vulnerable libraries.

What can we do about it?

greenkeeper.io

Discover vulnerabilities

snyk.io

Third party code in the browser

Third party code in the browser =
»Allowed« Cross Site Scripting (XSS)

<script>
- manipulate the siteʼs appearance
- manipulate cookies, localStorage, etc.
- steal session credentials, tokens, etc.
- load malicious code via XMLHttpRequest
- do whatever the heck you want
</script>

Limit sources for third party content

Content Security Policy

Content Security Policy:
A HTTP response header

Cache-Control: public
Content-Encoding: gzip
Content-Length: 2373
Content-Security-Policy: …
Content-Type:text/html; charset=utf-8
Date: Wed, 19 Oct 2016 11:22:05 GMT
…

Content Security Policy example

                        
# .htaccess

Header set Content-Security-Policy: ↩
  "script-src 'self' https://code.jquery.com"
                        
                    

Content Security Policy example


<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery.js"></script>
</head>
<body>
    <!-- this got injected somehow -->
    <script src="https://evil.com/evil.js"></script>
</body>
</html>
                    

Content Security Policy example

Loading/executing the script from evil.com is suppressed:

CSP warining message in Chrome Developer Tools

CSP Directives

  • child-src
  • connect-src
  • default-src
  • font-src
  • form-action
  • frame-ancestors
  • img-src
  • media-src
  • object-src
  • plugin-types
  • report-uri
  • sandbox
  • script-src
  • style-src

A more complex example

jQuery CDN, Google web fonts, embedded YouTube videos

Header set Content-Security-Policy: " \
  default-src 'none'; \
  script-src 'self' https://code.jquery.com; \
  style-src 'self' https://fonts.googleapis.com; \
  font-src https://themes.googleusercontent.com; \
  img-src 'self' data:; \
  frame-src https://www.youtube.com;"

CSP Sources

You can specify sources by scheme (data:, https:), hostname (example.com), fully qualified URI (https://example.com:443) or wildcard (*://*.example.com:*)

  • 'none': Forbids a source type entirely
  • 'self': matches the current origin (but not subdomains)
  • 'unsafe-inline': allows inline JavaScript and CSS
  • 'unsafe-eval': allows JavaScript parsing with eval(), etc.

Warning: 'unsafe-inline' / 'unsafe-eval' will execute all
inline scripts, including possible XSS vectors.

If you can't get around inline scripts, use 'nonce'


<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
    …
</script>
                    

Header set Content-Security-Policy: ↩
  "script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'"
                    

Testing your CSP rules

Content-Security-Policy-Report-Only: [policy]
CSP warining message in Chrome Developer Tools

Collect reports on what gets blocked


Header set Content-Security-Policy: …↩
  report-uri /my/reporting/endpoint
                    

You can also use report-uri.io for CSP data collection

Collect reports on what gets blocked


{
  "csp-report": {
    "document-uri": "http://example.com/signup.html",
    "referrer": "",
    "blocked-uri": "http://example.com/css/style.css",
    "violated-directive": "style-src cdn.example.com",
    "original-policy": "…"
  }
}
                    

Resources

HTML5 Rocks: An Introduction to Content Security Policy

content-security-policy.com

Browser support for Content Security Policy

Google Chrome Mozilla Firefox Internet Explorer Opera Safari (macOS/iOS) Android Stock Browser
25 4 10 15 6.1 4.4
caniuse.com

IE < Edge, some Android and/or older browsers may use
»X-Content-Security-Policy« or »X-Webkit-CSP«

Verify third party content:

Subresource Integrity


<script src="https://cdn.example.com/jquery.min.js"></script>
                    
  1. Download the file from a trusted source
  2. Verify its content
  3. Create a hash:
    $ cat jquery.min.js | openssl dgst -sha256 | openssl base64
    
    hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=
  4. Do the same for the file from the CDN server
  5. The hashes should match

<script
  src="https://cdn.example.com/jquery.min.js"
  crossorigin="anonymous"
  integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
></script>
                    

Browser support for Subresource Integrity

Google Chrome Mozilla Firefox Internet Explorer Opera Safari
macOS
Safari
iOS
Android Stock Browser
45 43 * 32 11 ** 5
caniuse.com

* MS Edge status: Windows Insider Preview Build
** WebKit status: Supported In Preview
(as of September 2017)

Recap

During development/build:

  • Take a close look at third party code you plan to use
  • Use reliable sources, keep your dependencies up to date
  • Have your dependencies checked for vulnerabilities

In the browser:

  • Be aware of content injection attacks (XSS)
  • Limit third party sources with Content Security Policy
  • Verify the content of external scripts with Subresource Integrity

Thank you!

Frederic Hemberger
frederic-hemberger.de
@fhemberger