A Primer in Single Page Application Security

30c94b96aa264994559fc0556b207bd8?s=47 Thomas Konrad
December 01, 2020

A Primer in Single Page Application Security

Single Page Application frameworks have brought us a boost in clean application architecture and also security, mainly because of better separation of concerns. But using a SPA framework alone does not automatically get you bullet-proof security. There is still a lot to look out for, and, for example, XSS is not a fully solved problem yet. In this talk, we’ll explore the most important security pitfalls SPA frameworks and how to solve them. We’ll also compare some of the security features of the most common SPA frameworks Angular, React, and Vue.js.


Thomas Konrad

December 01, 2020


  1. Classification: Public A Primer in Single Page Application Security Thomas

    Konrad, SBA Research WeAreDevelopers Live Week, December 1, 2020 SBA Research gGmbH, 2020
  2. Classification: Public 2 SBA Research gGmbH, 2020 $ whoami Thomas

    Konrad $ id uid=123(tom) gid=0(SBA Research) gid=1(Vienna, Austria) gid=2(Software Security) gid=3(Penetration Testing) gid=4(Software Development) gid=5(Security Training) gid=6(sec4dev Conference & Bootcamp)
  3. Classification: Public 3 „Can we have the slides?“ Yes you

    can! https://twitter.com/_thomaskonrad SBA Research gGmbH, 2020
  4. Classification: Public 4 What are Single Page Applications? SBA Research

    gGmbH, 2020 Image source: https://dotcms.com/blog/post/what-is-a- single-page-application-and-should-you-use-one-
  5. Classification: Public 5 SPAs: Advantages • Speed • Re-use of

    APIs • Offline app usage (PWA) • Separation of Concerns • Security. • But! SBA Research gGmbH, 2020 Image source: https://dotcms.com/blog/post/what-is-a- single-page-application-and-should-you-use-one-
  6. Classification: Public 6 Popular SPA Frameworks SBA Research gGmbH, 2020

  7. Classification: Public 7 SPA Security Concerns Tag Cloud SBA Research

    gGmbH, 2020 CORS Outdated Libraries Server-side Template Injection CSRF Authentication Transport Security
  8. Classification: Public 8 Cross-Site Scripting (XSS) And its relation to

    Single Page Application frameworks SBA Research gGmbH, 2020
  9. Classification: Public 9 Cross-Site Scripting (XSS)? SBA Research gGmbH, 2020

    Image source: https://www.imperva.com/learn/application- security/cross-site-scripting-xss-attacks/
  10. Classification: Public 10 SPAs and XSS? SPA XSS = DOM

    XSS Easy to introduce, hard to detect SBA Research gGmbH, 2020 https://www.youtube.com/watch?v=H_XDL1juAkQ
  11. Classification: Public 11 DOM XSS: A Basic Example • User-controlled

    input • DOM XSS sink SBA Research gGmbH, 2020 <script> var x = window.location.hash; document.querySelector('#el').innerHTML = x; </script> https://example.com/#<img src=x onerror=alert(1)/>
  12. Classification: Public 12 The DOM Is A Mess: XSS Sinks

    SBA Research gGmbH, 2020 Image source: https://www.youtube.com/watch?v=vYA81UAExKA https://github.com/wisec/domxsswiki/wiki
  13. Classification: Public 13 SPAs, innerHTML and XSS SBA Research gGmbH,

    2020 <span [innerHTML]="html"></span> Angular sanitizes this! <span dangerouslySetInnerHTML={html}></span> Makes you fear! <span v-html="html"></span> Makes you feel safe! const html = '<img src=x onerror=alert(1)/>'; Input: <img src=x />
  14. Classification: Public 14 SPAs, href and XSS SBA Research gGmbH,

    2020 <a [href]="link">Click</a> Angular sanitizes this! <a href={link}>Click</a> <a :href="link">Click</a> Makes you feel safe! const link = 'javascript:alert(1)'; Input: Makes you feel safe! unsafe:javascript:alert(1)
  15. Classification: Public 15 Other Potential DOM XSS Sinks in SPAs

    • These can be symptoms of bad application design! o Don‘t use dynamic src values for <script> tags and iframes o Dont‘s use dynamic style attributes o Be careful with dynamic resource URLs (images, fonts, etc.) SBA Research gGmbH, 2020
  16. Classification: Public 16 DOMPurify SBA Research gGmbH, 2020 import createDOMPurify

    from 'dompurify'; const purify = createDOMPurify(); purify.sanitize('<img src=x onerror=alert(1)//>’); // becomes <img src="x"> purify.sanitize('<svg><g/onload=alert(2)//<p>'); // becomes <svg><g></g></svg> purify.sanitize('<p>abc<iframe//src=jAva&Tab;script:aler t(3)>def</p>’); // becomes <p>abcdef</p> https://github.com/cure53/DOMPurify
  17. Classification: Public 17 Limitations of the Angular Sanitizer • It

    is strict and does not allow e.g. style, custom tags, customization • Then people do this: SBA Research gGmbH, 2020 https://angular.io/guide/security#sanitization-and-security- contexts import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; @Pipe({ name: 'sainitizeHtml', pure: false }) export class sanitizeHtmlPipe implements PipeTransform { constructor(private sanitizer: DomSanitizer) {} transform(content) { return this.sanitizer.bypassSecurityTrustHtml(content); } } Don’t do this!
  18. Classification: Public 18 Creating an Angular Pipe safeHtml SBA Research

    gGmbH, 2020 import createDOMPurify from 'dompurify'; @Pipe({ name: 'safeHtml'}) export class SafeHtmlPipe implements PipeTransform { private domPurify; constructor(private sanitized: DomSanitizer) { this.domPurify = createDOMPurify(); } transform(value) { return this.sanitized.bypassSecurityTrustHtml( this.domPurify.sanitize(value, { ADD_TAGS: ['custom-element'], // Explicitly allow this tag ADD_ATTR: ['x-data'] // Be careful with the style attribute! [1] [2] }) ); } } [1] https://code.google.com/archive/p/browsersec/wikis/Part1.wiki (see section „Cascading stylesheets“) [2] https://github.com/angular/angular/blob/master/packages/core/src/sanitization/style_sanitizer.ts
  19. Classification: Public 19 Don‘t do DOM Kung-fu! SBA Research gGmbH,

    2020 import { Component, VERSION } from '@angular/core'; @Component({ // ... }) export class AppComponent { elem = '<img src=x onerror=alert(1)>'; // Suppose this comes from an untrusted source func = 'alert(2);'; // Suppose this comes from an untrusted source ngOnInit() { document.write(this.elem); new Function(this.func)(); setTimeout(this.func, 0); setInterval(this.func, 0); eval(this.func); document.getElementById('my-element').innerHTML = this.elem; // More DOM XSS sinks here: https://github.com/wisec/domxsswiki/wiki/Sinks } }
  20. Classification: Public 20 Defense in Depth: Content Security Policy (CSP)

    • HTTP response header (or meta tag) • Created for reducing the risk of XSS • Whitelist for dynamic resources 2020 - SBA Research Content-Security-Policy: script-src 'self' cdn.example.com <script src="//cdn.example.com/jquery.min.js"></script> <script src="/js/app.js"></script> <script src="http://evil.com/pwnage.js"></script> Refused to load the script 'http://evil.com/pwnage.js' because it violates the following Content Security Policy directive: "script-src 'self' cdn.example.com".
  21. Classification: Public 21 The Heart of CSP • By default,

    o inline scripts are prohibited, o eval() is prohibited, o setTimeout() and setInterval() with inline code are prohibited, o the Function() constructor is prohibited SBA Research gGmbH, 2020
  22. Classification: Public 22 CSP and SPAs Are Friends If you

    go the happy path, there are no inline scripts! SBA Research gGmbH, 2020 <!DOCTYPE html> <html> <head> <title>My App</title> <link href=/js/app.4d3dc64c.js rel=preload as=script> <link href=/js/chunk-vendors.6cb936cb.js rel=preload as=script> <link href=/css/app.5a859f25.css rel=stylesheet> <link href=/css/chunk-vendors.87ee1366.css rel=stylesheet> </head> <body> <div id=app></div> <script src=/js/chunk-vendors.6cb936cb.js></script> <script src=/js/app.4d3dc64c.js></script> </body> </html>
  23. Classification: Public 23 The Future: Trusted Types • The idea

    o Don’t pass strings to DOM XSS sinks o Use objects instead o Make security decisions explicit o Strongly typed DOM API! SBA Research gGmbH, 2020 const el = document.createElement('div'); el.innerHTML = { toString: () => 'test' }; el.innerHTML; // "test"
  24. Classification: Public 24 Trusted Types: CSP SBA Research gGmbH, 2020

    Content-Security-Policy: trusted-types * const el = document.createElement('div'); el.innerHTML = '<img src=x onerror=alert(1)/>';
  25. Classification: Public 25 Trusted Types: Browser Support SBA Research gGmbH,

  26. Classification: Public 26 Trusted Types: Angular SBA Research gGmbH, 2020

  27. Classification: Public 27 SPA Developer’s Checklist: XSS ❑ Follow the

    “happy path” wherever possible ❑ A.k.a. avoid DOM Kung-fu ❑ Blacklist common DOM XSS sinks via the linter ❑ If you process HTML, sanitize it with DOMPurify ❑ Use event handlers instead of dynamic href ❑ Do not use dynamic src and style ❑ Be careful with dynamic resource URLs (images, fonts, etc.) ❑ Never use non-trusted templates ❑ Use a sensible Content Security Policy SBA Research gGmbH, 2020
  28. Classification: Public 28 Outdated Libraries And approaches to get them

    under control SBA Research gGmbH, 2020
  29. Classification: Public 29 Angular Project with Router and SCSS SBA

    Research gGmbH, 2020 > cloc node_modules ------------------------------------------------------ Language files blank comment code ------------------------------------------------------ JavaScript 16214 171274 786507 3076493 JSON 1887 298 0 247588 Markdown 1628 73253 4 177074 TypeScript 3069 16591 128264 153548 HTML 227 13191 214 25464 CSS 135 380 2275 22039 https://github.com/cure53/DOMPurify
  30. Classification: Public 30 SBA Research gGmbH, 2020 https://angular.io/guide/setup-local

  31. Classification: Public 31 npm audit SBA Research gGmbH, 2020 >

    npm audit # ... found 81959 vulnerabilities (81914 low, 45 moderate) in 2120806 scanned packages run `npm audit fix` to fix 81624 of them. 335 vulnerabilities require manual review. See the full report for details.
  32. Classification: Public 32 Automate Dependency Checks! 1. Trigger them automatically

    on every git push 2. Fail the build! 3. Do it regularly even if no pushes happen! SBA Research gGmbH, 2020
  33. Classification: Public 33 SPA Developer’s Checklist: Dependencies ❑ Choose your

    dependencies wisely ❑ Check your dependencies in an automated way ❑ Fail the build if there are severe vulnerabilities ❑ Run the check regularly even if there is no push ❑ Advanced ❑ Have a good test coverage ❑ A bot submits a pull request with updates ❑ Merge it automatically if tests are green SBA Research gGmbH, 2020
  34. Classification: Public 34 A Few More Things Transport Security, CSRF,

    CORS, Server-side Template Injection, WebSockets SBA Research gGmbH, 2020
  35. Classification: Public 35 SPA Developer’s Checklist: Multiple Topics ❑ Use

    TLS with Strict-Transport-Security and Preload! ❑ Use the SameSite Cookie flag or explicit auth against CSRF! ❑ Don’t use a * whitelist or Origin reflection for CORS! ❑ For WebSockets, check the Origin header on the server! ❑ Never render SPA templates dynamically on the server! SBA Research gGmbH, 2020
  36. Classification: Public 36 Philippe De Ryck Founder of Pragmatic Web

    Security, Google Developer Expert Alyssa Miller Hacker, AppSec Advocate, Public Speaker Tanya Janca Founder of We Hack Purple and author of "Alice and Bob Learn Application Security" Daniel Cuthbert Security Researcher Julien Vehent Security Architect and DevOps Advocate Johanna Ullrich Key Researcher at SBA Research sec4dev Security for developers! Feb 22 – 25, 2021 All virtual! https://sec4dev.io
  37. Classification: Public 37 sec4dev 2-day Bootcamps! https://sec4dev.io Mathias Tausig Martin

    Grottenthaler Hands-on AWS Cloud Security Philippe De Ryck Hands-on API security for developers Dimitrij Klesev Filip Nikolic Kubernetes Security Deep Dive
  38. Classification: Public 38 sec4dev Security for developers! Feb 22 –

    25, 2021 All virtual! https://twitter.com/sec4dev/status/ 1333672135613685764
  39. Classification: Public 39 Thomas Konrad SBA Research gGmbH Floragasse 7,

    1040 Wien +43 664 889 272 17 tkonrad@sba-research.org @_thomaskonrad SBA Research gGmbH, 2020
  40. Classification: Public 40 Photo by Emily Morter on Unsplash Follow

    me on Twitter! @_thomaskonrad
  41. Classification: Public 41 Resources • Krzysztof Kotowicz on Trusted Types

    & the end of DOM XSS: https://youtu.be/vYA81UAExKA • Philippe De Ryck – Angular / OWASP Top 10 Cheat Sheet: https://pragmaticwebsecurity.com/files/cheatsheets/angularowasptop10.pdf • Philippe De Ryck – React XSS Avoidance Cheat Sheet: https://pragmaticwebsecurity.com/files/cheatsheets/reactxss.pdf • W3C GitHub repository on Trusted Types: https://github.com/w3c/webappsec-trusted-types • Anguar DOM Sanitizer docs: https://angular.io/api/platform-browser/DomSanitizer • React docs on dangerouslySetInnerHTML: https://reactjs.org/docs/dom- elements.html#dangerouslysetinnerhtml • Vue.js docs on security: https://vuejs.org/v2/guide/security.html • GitHub docs on Security Alerts: https://help.github.com/en/github/managing-security- vulnerabilities/about-security-alerts-for-vulnerable-dependencies • GitLab docs on Dependency Scanning: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/ SBA Research gGmbH, 2020