フロントエンドエンジニアのためのセキュリティ対策 ~XSS編~ / #frontkansai 2019

フロントエンドエンジニアのためのセキュリティ対策 ~XSS編~ / #frontkansai 2019

FRONTEND CONFERENCE 2019( https://2019.kfug.jp )でセキュリティ、主にXSSについて話をしました。
demo: https://shisama.dev/xss-test

# Technical Topics
- 3 types of XSS ( Reflected XSS, Stored XSS, DOM based XSS)
- XSS with React
- DOMPurify
- Content Security Policy
- Trusted Types

5cf7e9533a457726cd51232e06c1da9a?s=128

Masashi Hirano

November 02, 2019
Tweet

Transcript

  1. Frontend Conference 2019 #frontkansai Masashi Hirano @shisama_ ϑϩϯτΤϯυΤϯδχΞͷͨΊͷ ηΩϡϦςΟରࡦ~XSSฤ~

  2. ฏ໺ ণ࢜ / Masashi Hirano @shisama_ shisama Node.js Core Collaborator

    ؔ੢NodeֶԂOrganizer
  3. ͜Μͳਓʹௌ͍ͯ΄͍͠ • ηΩϡϦςΟʹؔ৺͕͋Δํ • XSSʹֶ͍ͭͯͼ͍ͨํ(ॳதڃऀ) • WebΤϯδχΞ ಛʹϑϩϯτΤϯυΤϯδχΞ

  4. Agenda • WebͷηΩϡϦςΟಈ޲ • ੬ऑੑ(XSS)ͷ࢓૊Έͱରࡦ • XSSͷجૅ • ରࡦ: จࣈྻͷΤεέʔϓ

    • ରࡦ: ϒϥ΢βͷػೳ(CSPɺTrusted Types) • ηΩϡϦςΟ΁ͷҙࣝ
  5. WebͷηΩϡϦςΟಈ޲

  6. https://www.ipa.go.jp/security/vuln/report/vuln2019q3.html

  7. https://www.ipa.go.jp/security/vuln/report/vuln2019q3.html ಧग़݅਺ (2019೥7݄ʙ9݄)

  8. https://www.ipa.go.jp/security/vuln/report/vuln2019q3.html ෼ྨ ݄ʙ݄ ಧग़ड෇։͔࢝Βͷྦྷܭ ιϑτ΢ΣΞ੡඼ ݅  ݅ ΢ΣϒαΠτ ݅

     ݅ ߹ܭ ݅  ݅ ಧग़݅਺ (2019೥7݄ʙ9݄)
  9. https://www.ipa.go.jp/security/vuln/report/vuln2019q3.html ෼ྨ ݄ʙ݄ ಧग़ड෇։͔࢝Βͷྦྷܭ ιϑτ΢ΣΞ੡඼ ݅  ݅ ΢ΣϒαΠτ ݅

     ݅ ߹ܭ ݅  ݅ 8FC͕ιϑτ΢ΣΞʹ ൺ΂ͯഒҎ্ͷಧग़਺ ಧग़݅਺ (2019೥7݄ʙ9݄)
  10. https://www.ipa.go.jp/security/vuln/report/vuln2019q3.html ΢ΣϒαΠτͷ੬ऑੑͷछྨผͷಧग़        XSS

    (ΫϩεαΠτɾεΫϦϓςΟϯά) DNSͷઃఆෆඋ SQLΠϯδΣΫγϣϯ HTTPͷෆਖ਼ར༻ σΟϨΫτϦɾτϥόʔαϧ ϑΝΠϧͷޡެ։ ͦͷଞ
  11. https://www.youtube.com/watch?v=DDtM9caQ97I&t=633s

  12. https://www.hackerone.com/resources/top-10-vulnerabilities HackerOne 2018 Total Report

  13. https://blog.cybozu.io/entry/2019/06/20/160000 Cybozu BugBounty 2018

  14. https://www.owasp.org/index.php/Japan " ΠϯδΣΫγϣϯ 42-ΠϯδΣΫγϣϯɺίϚϯυΠϯδΣΫγϣϯͳͲ " ೝূͷෆඋ Ϣʔβʔͷೝূ৘ใͷ࿙Ӯ " ػඍͳ৘ใͷ࿐ग़ ࡒ຿৘ใ΍ݸਓ৘ใͳͲ઄औɺվ͟Μ

    " 9.-֎෦ΤϯςΟςΟࢀর 99& ֎෦ΤϯςΟςΟʹΑΔϦϞʔτίʔυͷ࣮ߦͳͲ " ΞΫηε੍ޚͷෆඋ ଞͷϢʔβʔͷσʔλ΍ݖݶͷมߋ " ෆద੾ͳηΩϡϦςΟઃఆ ҆શͰͳ͍ઃఆʹΑΔ໰୊ " ΫϩεαΠτεΫϦϓςΟϯά 944 ϒϥ΢β্ͰͷεΫϦϓτ࣮ߦʹΑΔ৘ใ࿙͍͑ͳͲ " ҆શͰͳ͍σγϦΞϥΠθʔγϣϯ ϦϞʔτ͔Βͷίʔυ࣮ߦ " ط஌ͷ੬ऑੑͷ͋Δίϯϙʔωϯτͷ࢖༻ ੬ऑੑͷ͋ΔϥΠϒϥϦͳͲʹΑΔ߈ܸ΍ѱӨڹ " ෆे෼ͳϩΪϯάͱϞχλϦϯά ϞχλϦϯάͷෆඋʹΑΔ߈ܸݕ஌࿙Ε OWASP Top10 2017
  15. ͜͜·Ͱͷ·ͱΊ: WebͷηΩϡϦςΟಈ޲ • ੬ऑੑͷଟ͕͘WebαΠτ͔Βൃੜ͢Δ΋ͷ • WebαΠτͷ੬ऑੑͰ࠷΋ଟ͍ͷ͸XSS • ಛʹॏେͳϦεΫ͕10ݸ͋Δ

  16. XSS

  17. XSSͷڴҖ • ίϯςϯπͷվ͟Μ • ηογϣϯϋΠδϟοΫ • ݸਓ৘ใ࿙Ӯ ※ҰྫͰ͢

  18. YouTubeͷඃ֐ࣄྫ • σϚͷϙοϓΞοϓදࣔɺଞαΠτ΁ͷϦμΠϨΫτͳͲ

  19. Twitterͷඃ֐ࣄྫ • ԕִϋΠδϟοΫʹΑΔϦπΠʔτ౤ߘ

  20. KADOKAWAͷඃ֐ࣄྫ • վ͟ΜʹΑΔϚϧ΢ΣΞ૊ΈࠐΈɺݸਓ৘ใ͕౪·ΕΔ

  21. 3छྨͷXSS • Reflected XSS • Stored XSS • DOM Based

    XSS
  22. ᶃ ߈ܸऀ͕༻ҙͨ͠ϖʔδʹΞΫηε Reflected XSS (൓ࣹܕXSS) ᶄ εΫϦϓτΛύϥϝʔλʹ ͯ͠ର৅αΠτʹભҠ <script>alert("XSS")</script> ?token=“”/><script>alert(“XSS")</script><div

    ᶅ εΫϦϓτ͕ ຒΊࠐ·ΕͨHTML
  23. Reflected XSS (൓ࣹܕXSS) <input type="hidden" name="token" value=#{qs.token} /> <input type="hidden"

    name="token" value=""/><script>alert("XSS")</script><div /> ΫΤϦετϦϯάͷ஋Λͦͷ··HTMLʹ൓ө
  24. Reflected XSS (൓ࣹܕXSS) <input type="hidden" name="token" value=#{qs.token} /> <input type="hidden"

    name="token" value=""/><script>alert("XSS")</script><div /> ΫΤϦετϦϯάͷ஋Λͦͷ··HTMLʹ൓ө
  25. ᶃ ϑΥʔϜ͔ΒPOST ᶄ POST͞Εͨ ஋Λͦͷ··อଘ <script>alert(“xss")</script> <li class="item"><script>alert(1)</script></li> ᶅ ଞͷϢʔβʔ͕αΠτʹΞΫηε

    ᶆ DBͷ஋ΛHTMLʹ൓ө Stored XSS (஝ੵܕXSS)
  26. ᶃ ϑΥʔϜ͔ΒPOST ᶄ POST͞Εͨ ஋Λͦͷ··อଘ <script>alert("XSS")</script> <li class="item"><script>alert(1)</script></li> ᶅ ଞͷϢʔβʔ͕αΠτʹΞΫηε

    ᶆ DBͷ஋ΛHTMLʹ൓ө Stored XSS (஝ੵܕXSS)
  27. DOM Based XSS const hash = decodeURIComponent(location.hash.slice(1)); document.querySelector('#result').innerHTML = hash;

    <img src=x onerror=alert('XSS')> ϩέʔγϣϯϋογϡͷ஋Λ JavaScriptͰૠೖ
  28. DOM Based XSS const hash = decodeURIComponent(location.hash.slice(1)); document.querySelector('#result').innerHTML = hash;

    <img src=x onerror=alert('XSS')> ϩέʔγϣϯϋογϡͷ஋Λ JavaScriptͰૠೖ
  29. DOM Based XSS const hash = decodeURIComponent(location.hash.slice(1)); document.querySelector('#result').innerHTML = hash;

    ιʔε (Source) γϯΫ (Sink) ୅දతͳSink - innerHTML - location.href - document.write - jQuery() ͳͲ ୅දతͳSource - location.hash - location.href - document.referrer - IndexedDB ͳͲ
  30. 3छྨͷXSS • Reflected XSS • Stored XSS • DOM Based

    XSS ࠷ऴతʹ͸ඃ֐ऀͷϒϥ΢β্Ͱ JavaScript͕࣮ߦ͞ΕΔ
  31. ओͳXSSͷରࡦ • ةݥͳจࣈྻͷΤεέʔϓɾ࡟আ • ϒϥ΢βͷػೳΛ࢖͏

  32. ओͳXSSͷରࡦ • ةݥͳจࣈྻͷΤεέʔϓɾ࡟আ • ϒϥ΢βͷػೳΛ࢖͏

  33. HTMLಛघจࣈͷΤεέʔϓॲཧ <script> cookieHijack() </script> &lt;script&gt; cookieHijack() &lt;/script&gt; & < ม׵લ

    ม׵ޙ > “ ‘ &amp; &lt; &gt; &quot; &#039; Τεέʔϓॲཧ
  34. ةݥͳจࣈྻͷ࡟আॲཧ <img src=x onerror=“javascript:alert('XSS')" /> ࡟আॲཧ <img src=x />

  35. จࣈྻͷΤεέʔϓɾ࡟আॲཧͷ࣮૷ function sanitizer(str) { return str .replace(/&/g, "&amp;") .replace(/</g, "&lt;")

    .replace(/>/g, "&gt;") .replace(/"/g, "&quot;") .replace(/'/g, "&#039;") ... }
  36. จࣈྻͷΤεέʔϓɾ࡟আॲཧͷ࣮૷ function sanitizer(str) { return str .replace(/&/g, "&amp;") .replace(/</g, "&lt;")

    .replace(/>/g, "&gt;") .replace(/"/g, "&quot;") .replace(/'/g, "&#039;") ... } ࣮૷͢Δ͕େม ςετ΋େม ࢓༷࿙Ε͍ͯͳ͍͔ෆ҆
  37. ݴޠػೳ΍OSSΛ࢖͏ • ϓϩάϥϛϯάݴޠ΍ओཁͳϑϨʔϜϫʔΫʹ͸Τεέʔϓػೳ Λඋ͍͑ͯΔ • Τεέʔϓ༻ͷϥΠϒϥϦ΋ଟ਺ଘࡏ͠·͢

  38. https://reactjs.org/docs/introducing-jsx.html#jsx-prevents-injection-attacks

  39. const App = props => ( <div className="App"> <script>alert(“xss")</script> </div>

    ); React DOM escapes any values by default
  40. const App = props => ( <div className="App"> <script>alert(“xss")</script> </div>

    ); React DOM escapes any values by default 944͸ى͖ͳ͍
  41. const App = (props) => ( <div className="App"> <a href=“javascript:alert(“xss")">click

    me!</a> </div> ); React DOM escapes any values by default
  42. const App = (props) => ( <div className="App"> <a href=“javascript:alert(“xss")">click

    me!</a> </div> ); React DOM escapes any values by default
  43. ReactͷXSS • javascript:εΩʔϜͳͲଐੑ஋͸Τεέʔϓ͞Εͳ͍ • Ϣʔβʔ͕ೖྗͰ͖Ε͹XSS͸ൃੜ͢Δ <div className=“App"> <form> <input value={title}

    onChange={onChangeTitle} /> <input value={url} onChange={onChangeUrl} /> </form> <a href={url}>{title}</a> </div>
  44. const Link = props => { const protocol = new

    URL(props.url).protocol; const safeUrl = /^https?:/.test(protocol) ? props.url : ""; return <a href={safeUrl}>{props.children}</a>; }; const App = () => { const { url, title, onChangeUrl, onChangeTitle } = useInput(); return ( <div className="App"> <form> <input value={title} onChange={onChangeTitle} /> <input value={url} onChange={onChangeUrl} /> </form> <Link url={url}>{title}</Link> </div> ); };
  45. const Link = props => { const protocol = new

    URL(props.url).protocol; const safeUrl = /^https?:/.test(protocol) ? props.url : ""; return <a href={safeUrl}>{props.children}</a>; }; const App = () => { const { url, title, onChangeUrl, onChangeTitle } = useInput(); return ( <div className="App"> <form> <input value={title} onChange={onChangeTitle} /> <input value={url} onChange={onChangeUrl} /> </form> <Link url={url}>{title}</Link> </div> ); }; IUUQ·ͨ͸IUUQTϓϩτίϧͷΈڐՄ͢Δ͜ͱ ͰɺzKBWBTDSJQUz͔Β࢝·ΔจࣈྻΛແ֐Խ <a href="">click me!</a>
  46. https://github.com/facebook/react/pull/15047

  47. https://github.com/cure53/DOMPurify

  48. $ npm install dompurify npm <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/ 2.0.3/purify.min.js"></script> CDN DOMPurify

  49. DOMPurify const untrustedStr = location.hash; // <img src=x onerror="javascript:alert(1)" />

    const trustedStr = DOMPurify.sanitize(untrustedHTML); $('#foo').innerHTML = trustedStr; // <img src=x />
  50. DOMPurify const untrustedStr = location.hash; // <img src=x onerror="javascript:alert(1)" />

    const trustedStr = DOMPurify.sanitize(untrustedHTML); $('#foo').innerHTML = trustedStr; // <img src=x /> MPDBUJPOIBTIͷ஋͕ ͦͷ··4JOL͞ΕͨΒ εΫϦϓτ͕࣮ߦ͞ΕΔ
  51. DOMPurify const untrustedStr = location.hash; // <img src=x onerror="javascript:alert(1)" />

    const trustedStr = DOMPurify.sanitize(untrustedHTML); $('#foo').innerHTML = trustedStr; // <img src=x /> %0.1VSJGZTBOJUJ[FʹΑΓ ةݥͳจࣈྻ͚ͩআڈ͞ΕΔ
  52. https://developer.cybozu.io/hc/ja/articles/360001038846-DOMPurifyΛ࢖ͬͯ҆શʹDOMΛදࣔ͠Α͏-

  53. ओͳXSSͷରࡦ • ةݥͳจࣈྻͷΤεέʔϓɾ࡟আ • ϒϥ΢βͷػೳΛ࢖͏

  54. ϒϥ΢β͸༷ʑͳ੬ऑੑରࡦͷػೳΛඋ͍͑ͯΔ X-XSS-Protection HttpOnly SameSite Content Security Policy Referer Referrer-Policy XSS

    Auditor ※ܝࡌ͸Ұ෦ Fetch Meta
  55. https://www.w3.org/TR/CSP2/

  56. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy

  57. https://caniuse.com/#feat=mdn-http_headers_csp_content-security-policy

  58. ▼ Response Headers content-security-policy: script-src ‘self’ *.trusted.com σΟϨΫςΟϒ ιʔε •

    HTTPϨεϙϯεϔομʔʹ௥Ճ͢Δ • Ϧιʔεͷऔಘઌ΍εΫϦϓτͷ࣮ߦΛࢦఆͨ͠ιʔεͷΈʹ੍ݶͰ͖Δ • script-src ‘self’; img-src *.trusted.comͷ ͷΑ͏ʹෳ਺ઃఆ΋Մೳ script-src ‘self’; img-src *.trusted.com Content Security Policy
  59. <meta http-equiv="Content-Security-Policy" content="script-src 'self'"> Content Security Policy • HTMLͷ<meta>λάͰࢦఆͰ͖ΔͷͰϑϩϯτΤϯυ͚ͩͰ΋࣮૷Մೳ •

    <meta>ΑΓઌʹઃఆ͞Εͨ஋ͷ্ॻ͖ෆՄ • <meta>ΑΓઌʹಡΈࠐ·ΕͨϦιʔε΍εΫϦϓτʹ͸ద༻Ͱ͖ͳ͍ • <meta>Ͱ͸ઃఆͰ͖ͳ͍σΟϨΫςΟϒ͕͋Δ e.g. report-only
  60. ▼ Response Headers content-security-policy-report-only: script-src ‘self’ *.trusted.com report-uri /csp-report •

    ࣮ࡍͷCSPΛద༻ͤͣʹϨϙʔτ͚ͩૹΔ͜ͱ͕Մೳ • CSPͰڐՄ͞Ε͍ͯͳ͍৔߹ɺϨϙʔτΛPOST͢Δ • CSPͷຊ൪ಋೖલʹӨڹΛ֬ೝ͢Δ͜ͱ͕Մೳ • <meta>λάͰͷઃఆ͸ෆՄ Content-Security-Policy-Report-Only
  61. { "csp-report": { "document-uri": "http://example.com/index.html", "referrer": "", "blocked-uri": "http://invalid-cdn.com/js/react.js", "violated-directive":

    "script-src self *.trusted.com*", "original-policy": "script-src 'self' *.trusted.com; report-uri /csp-report/", "disposition": "report" } } Ϩϙʔτͷྫ
  62. content-security-policy: script-src ‘self’ *.trusted.com : εΫϦϓτͷ࣮ߦ੍ݶ : ڐՄ͢ΔιʔεΛࢦఆ Content Security

    Policyͷ஋ʹ͍ͭͯ script-src ‘self’ *.trusted.com Ωʔϫʔυ ϗετ
  63. σΟϨΫςΟϒ DPOOFDUTSD 9)3ɺ8FC4PDLFUͳͲͷ੍ݶ EFGBVMUTSD ଞͷϑΣονσΟϨΫςΟϒͷϑΥʔϧόοΫ JNHTSD ը૾ͷಡΈࠐΈઌΛ੍ݶ NFEJBTSD BVEJPWJEFPͷಡΈࠐΈઌΛ੍ݶ TDSJQUTSD

    εΫϦϓτͷ࣮ߦ৔ॴΛ੍ݶ TUZMFTSD ελΠϧͷద༻৔ॴΛ੍ݶ ୅දతͳσΟϨΫςΟϒ(ϑΣονͷҰ෦)
  64. content-security-policy: script-src ‘self’ <img src=x onerror=alert('XSS')> <script>alert("XSS")</script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> ϗετͱϙʔτ͕ಉ͡εΫϦϓτͷΈڐՄ

  65. content-security-policy: script-src ‘self’ <img src=x onerror=alert('XSS')> <script>alert("XSS")</script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> ϗετͱϙʔτ͕ಉ͡εΫϦϓτͷΈڐՄ

    ࢦఆ͞Εͨϗετͱҧ͏ͷͰېࢭ ❌
  66. content-security-policy: script-src ‘self’ <img src=x onerror=alert('XSS')> <script>alert("XSS")</script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> ϗετͱϙʔτ͕ಉ͡εΫϦϓτͷΈڐՄ

    ❌ ❌ ΠϯϥΠϯεΫϦϓτ͸ېࢭ
  67. content-security-policy: script-src ‘self’ <img src=x onerror=alert('XSS')> <script>alert("XSS")</script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> ϗετͱϙʔτ͕ಉ͡εΫϦϓτͷΈڐՄ

    ❌ ❌ ❌ Πϕϯτଐੑ΍KBWBTDSJQUͳͲ΋ېࢭ
  68. content-security-policy: script-src ‘self’ ‘unsafe-inline’ ΠϯϥΠϯεΫϦϓτͷڐՄ • ΠϯϥΠϯεΫϦϓτΛڐՄ͍ͨ͠৔߹ • ໊લͷ௨Γunsafe(҆શͰ͸ͳ͍)

  69. https://www.w3.org/TR/CSP2/#source-list-valid-nonces CSP Lv.2 nonce

  70. content-security-policy: script-src ‘nonce-EDNnf03nceIOfn39fn3e9h3sdfa' <script nonce=“EDNnf03nceIOfn39fn3e9h3sdfa">alert("OK")</script> <script>alert(“NG")</script> <script nonce=“CntdRvwQ7oWoqs7zjGRVLRr7oad">alert("NG")</script> OPODFCBTFΤϯίʔυ஋

  71. content-security-policy: script-src ‘nonce-EDNnf03nceIOfn39fn3e9h3sdfa' <script nonce=“EDNnf03nceIOfn39fn3e9h3sdfa">alert("OK")</script> <script>alert(“NG")</script> <script nonce=“CntdRvwQ7oWoqs7zjGRVLRr7oad">alert("NG")</script> OPODFͷ஋͕Ұக͍ͯ͠ΔͷͰ࣮ߦΛڐՄ OPODFCBTFΤϯίʔυ஋

  72. content-security-policy: script-src ‘nonce-EDNnf03nceIOfn39fn3e9h3sdfa' <script nonce=“EDNnf03nceIOfn39fn3e9h3sdfa">alert("OK")</script> <script>alert(“NG")</script> <script nonce=“CntdRvwQ7oWoqs7zjGRVLRr7oad">alert("NG")</script> OPODF஋͕ෆҰக·ͨ͸ະࢦఆͳͷͰ࣮ߦΛېࢭ OPODFCBTFΤϯίʔυ஋

  73. content-security-policy: script-src ‘nonce-EDNnf03nceIOfn39fn3e9h3sdfa' <script nonce=“EDNnf03nceIOfn39fn3e9h3sdfa">alert("OK")</script> • nonceͷ஋͸αʔόʔଆͰϦΫΤετ͝ͱʹมߋ͢Δ͜ͱ • ਪଌ͞Εͳ͍ϥϯμϜͳ஋ʹ͢Δ͜ͱ •

    scriptλάΛಈతʹੜ੒Ͱ͖ͳ͍ nonceͷ஫ҙ఺
  74. content-security-policy: script-src ‘nonce-EDNnf03nceIOfn39fn3e9h3sdfa’ ‘strict-dynamic’ <script nonce="EDNnf03nceIOfn39fn3e9h3sdfa"> const script = document.createElement('script');

    script.src = ‘/static/js/main.js’; document.head.appendChild(script); </script> CSP Lv.3 strict-dynamic QBSTFSJOTFSUFEͰͳ͍TDSJQUͷಈతੜ੒͕Մೳ ※parser-inserted = HTMLύʔαʔ΍XMLύʔαʔʹΑͬͯૠೖ͞ΕΔ͜ͱ
  75. content-security-policy: script-src ‘nonce-EDNnf03nceIOfn39fn3e9h3sdfa’ ‘strict-dynamic’ <script nonce="EDNnf03nceIOfn39fn3e9h3sdfa"> const script = document.createElement('script');

    script.textContent = location.hash.slice(1); document.head.appendChild(script); </script> location.hashͷ஋ΛऔΔͱʁ
  76. content-security-policy: script-src ‘nonce-EDNnf03nceIOfn39fn3e9h3sdfa’ ‘strict-dynamic’ <script nonce="EDNnf03nceIOfn39fn3e9h3sdfa"> const script = document.createElement('script');

    script.textContent = location.hash.slice(1); document.head.appendChild(script); </script> location.hashͷ஋ΛऔΔͱʁ
  77. https://w3c.github.io/webappsec-trusted-types/dist/spec/

  78. Trusted Types URL String HTML String Script String Scritp URL

    TrustedURL TrustedHTML TrustedScript TrustedScriptURL TrustedTypes จࣈྻΛ҆શͳܕʹม׵ͯ͠ݕূ͢Δ
  79. content-security-policy: require-trusted-types-for ‘script’; trusted-types; script.textContent = location.hash.slice(1); document.head.appendChild(script); Trusted Types

    ҆શͳܕͰ͸ͳ͍ͷͰεΫϦϓτ͸࣮ߦ͞Εͳ͍
  80. content-security-policy: require-trusted-types-for ‘script’; trusted-types *; script-src ‘nonce-EDNnf03nceIOfn39fn3e9h3sdfa’ ‘strict-dynamic’ <script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">

    const script = document.createElement('script'); script.textContent = location.hash.slice(1); document.head.appendChild(script); </script>
  81. content-security-policy: require-trusted-types-for ‘script’; trusted-types *; script-src ‘nonce-EDNnf03nceIOfn39fn3e9h3sdfa’ ‘strict-dynamic’ <script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">

    const script = document.createElement('script'); script.textContent = location.hash.slice(1); document.head.appendChild(script); </script> 944͸ى͖ͳ͍
  82. content-security-policy: require-trusted-types-for ‘script'; trusted-types my-policy; const myPolicy = trustedTypes.createPolicy('my-policy', {

    createHTML: (s) => { return customSanitize(s) }, createURL: (s) => { /* ΤεέʔϓॲཧͳͲ */ }, createScript: (s) => { /* εΫϦϓτ಺༰ͷνΣοΫͳͲ */ }, }) Trusted Types Policy จࣈྻΛ҆શͳܕʹม׵͢ΔϙϦγʔΛੜ੒͢Δ
  83. Trusted Types Policy ϙϦγʔʹΑͬͯੜ੒͞Εͨܕ͸࣮ߦՄೳʹͳΔ const hash = decodeURIComponent(location.hash.slice(1)); const trustedHtml

    = myPolicy.createHTML(hash) document.body.innerHTML = trustedHtml; content-security-policy: require-trusted-types-for ‘script’; trusted-types my-policy;
  84. const myPolicy = trustedTypes.createPolicy("my-policy", { createHTML: (s) => { return

    DOMPurify.sanitize(s); } }); Trusted Types & DOMPurify const hash = decodeURIComponent(location.hash.slice(1)); const trustedHtml = myPolicy.createHTML(hash) document.body.innerHTML = trustedHtml; <img src=x onerror=“javascript:alert(‘xss’)”/> <img src=x />
  85. https://github.com/w3c/webappsec-trusted-types/pull/205 5SVTUFE5ZQFTUSVTUFE5ZQFTʹϦωʔϜ͞Εͨ

  86. https://www.chromestatus.com/feature/5650088592408576 Chrome 83 ͔Β͸σϑΥϧτͰ༗ޮ

  87. chrome://flags/#enable-experimental-web-platform-features ΋͠$ISPNFҎԼΛ࢖͍ͬͯΔ৔߹

  88. <script src="https://w3c.github.io/webappsec-trusted-types/dist/es5/trustedtypes.build.js" data-csp="trusted-types my-policy“></script> <script> trustedTypes.createPolicy('my-policy', ...); trustedTypes.createPolicy('unknown', ...); //

    throws document.body.innerHTML = 'foo'; // throws Trusted Types Polyfill npm CDN $ npm install trusted-types import {tt} from 'trusted-types' tt.createPolicy('my-policy', ...);
  89. • Demo Page: https://shisama.dev/xss-test/ • GitHub: https://github.com/shisama/xss-test/ • DOM Based

    XSS • CSP • Trusted Types ※devToolsͷconsoleΛ։͖ͳ͕Β֬ೝ͍ͯͩ͘͠͞
  90. https://github.com/facebook/react/pull/16157/

  91. ͜͜·Ͱͷ·ͱΊ: XSS • XSS͸ϒϥ΢βͰεΫϦϓτΛ࣮ߦ͢Δ߈ܸख๏ • ೖྗ͞ΕͨจࣈྻͷΤεέʔϓͰରࡦՄೳ • ϒϥ΢βͷػೳͰରࡦՄೳ • CSP΍Trusted

    TypesͰΑΓ҆શʹXSSΛ๷͙͜ͱ͕Մೳ
  92. ηΩϡϦςΟ΁ͷҙࣝ

  93. https://www.amazon.co.jp/dp/4797393165

  94. https://www.amazon.co.jp/dp/4797393165 “੬ऑੑͱ͸ɺʮѱ༻Ͱ͖Δόάʯ” ʰମܥతʹֶͿ ҆શͳWebΞϓϦέʔγϣϯͷ࡞Γํ ୈ̎൛ʱ ಙؙ ߒ (ஶ)

  95. ੬ऑੑ͸όάͰ͋Δͱ͍͏ҙࣝΛ࣋ͭ • ཁ݅ఆٛ΍࢓༷ࡦఆͰηΩϡϦςΟʹؔͯ͠FIX͢Δ • ػೳςετ͚ͩͰͳ͘ηΩϡϦςΟςετΛߦ͏ • ੬ऑੑ(όά)͕ݟ͔ͭΕ͹؅ཧͯ͠༏ઌ౓Λ͚ͭΔ

  96. ୭͠΋͕ ηΩϡϦςΟͷΤΩεύʔτͰ͸ͳ͍

  97. ͲͷΑ͏ʹ੬ऑੑΛ֬ೝ͢Ε͹Α͍͔

  98. https://www.ipa.go.jp/security/vuln/websecurity.html

  99. ʰ҆શͳ΢ΣϒαΠτͷ࡞ΓํʱνΣοΫϦετͰ͸͡ΊΔ

  100. • ֤੬ऑੑʹର͢Δʮࠜຊతղܾʯʮอݥతղܾʯ͕هࡌ͞Ε͍ͯΔ

  101. ҎԼͷ੬ऑੑ͕هࡌ͞Ε͍ͯΔ • ̍ʣ SQL ΠϯδΣΫγϣϯ • ̎ʣ OS ίϚϯυɾΠϯδΣΫγϣϯ •

    ̏ʣ ύε໊ύϥϝʔλͷະνΣοΫʗ σΟϨΫτϦɾτϥόʔαϧ • ̐ʣ ηογϣϯ؅ཧͷෆඋ • ̑ʣ ΫϩεαΠτɾεΫϦϓςΟϯά • ̒ʣ CSRFʢΫϩεαΠτɾϦΫΤετɾ ϑΥʔδΣϦʣ • ̓ʣ HTTP ϔομɾΠϯδΣΫγϣϯ • ̔ʣ ϝʔϧϔομɾΠϯδΣΫγϣ ϯ • ̕ʣ ΫϦοΫδϟοΩϯά • ̍̌ʣόοϑΝΦʔόʔϑϩʔ • ̍̍ʣΞΫηε੍ޚ΍ೝՄ੍ޚͷܽ མ
  102. ηΩϡϦςΟνΣοΫʹ࢖͑Δ΋ͷҰྫ • Ϧετ • ΢Σϒ݈߁਍அ࢓༷ • OWASP Cheat Sheet Series

    • HTML5 Security Cheat Sheet • πʔϧ • OWASP ZAP • Vuls • VAddy
  103. جຊతͳ੬ऑੑͷ
 νΣοΫ΍ରࡦ͸Ͱ͖Δ

  104. όάΛະવʹ๷͗ɺ ൃݟͨ͠Β؅ཧ͠վम͠Α͏ “੬ऑੑͱ͸ɺʮѱ༻Ͱ͖Δόάʯ”

  105. ·ͱΊ • ࠷΋ଟ͍੬ऑੑ͸XSS • XSSରࡦʹ͸จࣈྻΛΤεέʔϓ͢Δ • ϒϥ΢β͸CSPͳͲ੬ऑੑରࡦͷػೳΛඋ͍͑ͯΔ • ੬ऑੑ͸όάͱ͍͏ҙࣝΛ࣋ͭ͜ͱ

  106. ࢀߟ • ͦΖͦΖCSP Lv.2 nonce΍Ζ͏ - teppeis blog • Masato

    Kinugawa Security Blog: CVE-2018-5175: FirefoxͰCSPͷstrict-dynamic όΠύε • ҆શͳจࣈྻͰ͋ΔͱܕͰݕূ͢Δ Trusted Types ʹ͍ͭͯ - Jxck • Avoiding XSS in React is Still Hard - javascript-security - Medium • Securing Web Apps with Modern Platform Features (Google I/O ’19)
  107. Thanks. @shisama_ shisama