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

Account hijacking using "dirty dancing" in sign...

Frans Rosén
August 30, 2022

Account hijacking using "dirty dancing" in sign-in OAuth-flows

Slides from my talk at Sikkerhetsfestivalen Lillehammer in Aug 2022.

Frans Rosén

August 30, 2022
Tweet

More Decks by Frans Rosén

Other Decks in Research

Transcript

  1. PUBLIC Rundown 2 • Intro • Elevator pitch • History

    • Theory • Results and findings • Demo • Conclusions
  2. PUBLIC Introduction 3 • Security advisor @ Detectify • Bug

    hunter since 2012 • I killed TLS-SNI-01 • My blog post got Trump hacked
  3. PUBLIC OAuth for web apps 10 reddit.com Sign in with

    Google reddit.com/oauth?code=SECRET&…
  4. PUBLIC OAuth for web apps 11 reddit.com Sign in with

    Google reddit.com/oauth?code=SECRET&… Signed in!
  5. PUBLIC Common response types 13 • code + state 


    https://example.com/?code=xxx&state=yyy 
 Website need to ask provider to validate. Code can only be used once 

  6. PUBLIC Common response types 14 • code + state 


    https://example.com/?code=xxx&state=yyy 
 Website need to ask provider to validate. Code can only be used once 
 • id_token 
 https://example.com/#id_token=eyJ… 
 Signed info about user using public cert of provider
  7. PUBLIC Common response types 15 • code + state 


    https://example.com/?code=xxx&state=yyy 
 Website need to ask provider to validate. Code can only be used once 
 • id_token 
 https://example.com/#id_token=eyJ… 
 Signed info about user using public cert of provider 
 • token 
 https://example.com/#access_token=xxx 
 Token can be used with provider’s API
  8. PUBLIC Common response modes 16 • Query 
 https://example.com?code=x&state=y 


    Query parameters sent to the website. Only allowed for response type code 

  9. PUBLIC Common response modes 17 • Query 
 https://example.com?code=x&state=y 


    Query parameters sent to the website. Only allowed for response type code 
 • Fragment 
 https://example.com#access_token=xxx 
 Does not end up in server logs, only reached by Javascript 

  10. PUBLIC Common response modes 18 • Query 
 https://example.com?code=x&state=y 


    Query parameters sent to the website. Only allowed for response type code 
 • Fragment 
 https://example.com#access_token=xxx 
 Does not end up in server logs, only reached by Javascript 
 • Web message 
 postMessage({accessToken: 'xxx'}, 'https://example.com') 
 Sent as a postMessage to the website 

  11. PUBLIC Common response modes 19 • Query 
 https://example.com?code=x&state=y 


    Query parameters sent to the website. Only allowed for response type code 
 • Fragment 
 https://example.com#access_token=xxx 
 Does not end up in server logs, only reached by Javascript 
 • Web message 
 postMessage({accessToken: 'xxx'}, 'https://example.com') 
 Sent as a postMessage to the website 
 • Form post 
 <form method=POST action=https://example.com>... 
 A form that posts data back to the website
  12. PUBLIC Short answer: The URL becomes sensitive Why is account

    hijacking with OAuth a thing? example.com/oauth/#access_token=SECRETTOKEN example.com/oauth/?code=SECRETCODE
  13. PUBLIC OAuth hijacking pioneers 22 Nir Goldschlager in 2013 https://wagcenter.com/social-networks-wags/nir-goldshlager-facebooks-deadliest-hacker-saver/

    https://news.softpedia.com/news/Expert-Shows-How-Hackers-Can-Use-CSRF-Browser-Vulnerability-262109.shtml Egor Homakov in 2012
  14. PUBLIC Issues back then 25 • "Referer" leaked URL incl

    query parameters, 
 including loading of images
  15. PUBLIC Issues back then 26 • "Referer" leaked URL incl

    query parameters, 
 including loading of images • XSS was even more common
  16. PUBLIC Issues back then 27 • "Referer" leaked URL incl

    query parameters, 
 including loading of images • XSS was even more common • Content Security Policy (CSP) did not exist
  17. PUBLIC Issues back then 28 • "Referer" leaked URL incl

    query parameters, 
 including loading of images • XSS was even more common • Content Security Policy (CSP) did not exist • Large OAuth providers (like FB) made it easy to do wrong
  18. PUBLIC What if… 35 • postMessage-listeners without XSS could still

    leak the URL cross-domain? • I have ignored these earlier?
  19. PUBLIC What if… 36 • postMessage-listeners without XSS could still

    leak the URL cross-domain? • I have ignored these earlier? • More complex flows? Not just "give me URL"
  20. PUBLIC What if… 37 • postMessage-listeners without XSS could still

    leak the URL cross-domain? • I have ignored these earlier? • More complex flows? Not just "give me URL" • A way to force OAuth-flow to fail halfway?
  21. PUBLIC Break "state" intentionally 45 • "state" is a param

    to make sure the user that started the flow is the one finishing it
  22. PUBLIC Break "state" intentionally 46 • "state" is a param

    to make sure the user that started the flow is the one finishing it • It’s the website’s responsibility to validate it
  23. PUBLIC Break "state" intentionally 47 • "state" is a param

    to make sure the user that started the flow is the one finishing it • It’s the website’s responsibility to validate it • If validation fails, code is never sent back to provider
  24. PUBLIC Break "state" intentionally 50 1. Attacker prepares "state" 2.

    Attacker makes malicious page 3. Victim clicks link
  25. PUBLIC Break "state" intentionally 51 1. Attacker prepares "state" 2.

    Attacker makes malicious page 3. Victim clicks link 4. "state" invalid 
 for victim
  26. PUBLIC Response-type/mode switching 55 • Most providers allow changing type/mode

    • Website gets confused with a different one • No real option to disable types/modes
  27. PUBLIC Redirect URI modifications 62 • Case shifting 
 example.com/oauth

    -> example.com/oAUth#access-token=xxx 
 • Path appending 
 example.com/oauth -> example.com/oauth/x#access-token=xxx 

  28. PUBLIC Redirect URI modifications 63 • Case shifting 
 example.com/oauth

    -> example.com/oAUth#access-token=xxx 
 • Path appending 
 example.com/oauth -> example.com/oauth/x#access-token=xxx 
 • Parameter appending 
 example.com/oauth?code=x -> example.com/oauth?code=x&code=xxx 
 

  29. PUBLIC Non-happy path! Now what? 70 • Error page, 404

    och 500 or similar 
 • Redirect to start page 

  30. PUBLIC Non-happy path! Now what? 71 • Error page, 404

    och 500 or similar 
 • Redirect to start page 
 • Redirect to login page 

  31. PUBLIC Non-happy path! Now what? 72 • Error page, 404

    och 500 or similar 
 • Redirect to start page 
 • Redirect to login page 
 • Redirect to login page with parameters removed 

  32. PUBLIC Non-happy path! Now what? 73 • Error page, 404

    och 500 or similar 
 • Redirect to start page 
 • Redirect to login page 
 • Redirect to login page with parameters removed 
 • Redirect back to OAuth provider again
  33. PUBLIC Non-happy path! Now what? 74 • Error page, 404

    och 500 or similar 
 • Redirect to start page 
 • Redirect to login page 
 • Redirect to login page with parameters removed 
 • Redirect back to OAuth provider again My focus
  34. PUBLIC Weak postMessage-listeners leaking URL 83 • The one I

    expected to find • Message cross-domain containing URL
  35. PUBLIC Weak postMessage-listeners leaking URL 87 2. Attacker page to

    Reddit: postMessage(..) 1. Victim clicks link, opens popup, uses wrong response type
  36. PUBLIC Weak postMessage-listeners leaking URL 88 2. Attacker page to

    Reddit: postMessage(..) 3. Reddit responds: postMessage(reddit.com/ #access-token=xxx) 1. Victim clicks link, opens popup, uses wrong response type
  37. PUBLIC Weak postMessage-listeners leaking URL 89 2. Attacker page to

    Reddit: postMessage(..) 3. Reddit responds: postMessage(reddit.com/ #access-token=xxx) 1. Victim clicks link, opens popup, uses wrong response type 4. Attacker got the token!
  38. PUBLIC XSS on sandbox/third-party domain getting URL 90 • URL

    gets transferred to sandbox/third-party
  39. PUBLIC XSS on sandbox/third-party domain getting URL 91 • URL

    gets transferred to sandbox/third-party • Sandbox has XSS
  40. PUBLIC XSS on sandbox/third-party domain getting URL 92 • URL

    gets transferred to sandbox/third-party • Sandbox has XSS • Two windows with same origin can reach each other
  41. PUBLIC XSS on sandbox/third-party domain getting URL 93 • URL

    gets transferred to sandbox/third-party • Sandbox has XSS • Two windows with same origin can reach each other • 2 days after my report, Youssef Sammouda made a similar finding on FB
  42. PUBLIC XSS on sandbox/third-party domain getting URL 96 1. Victim

    clicks link, XSS in sandbox iframe 2. Opens popup XSS
  43. PUBLIC XSS on sandbox/third-party domain getting URL 97 1. Victim

    clicks link, XSS in sandbox iframe 2. Opens popup, uses wrong response type XSS
  44. PUBLIC XSS on sandbox/third-party domain getting URL 98 1. Victim

    clicks link, XSS in sandbox iframe 2. Opens popup, uses wrong response type XSS 3. Loads sandbox iframe, URL 
 of main window is transferred
  45. PUBLIC XSS on sandbox/third-party domain getting URL 99 1. Victim

    clicks link, XSS in sandbox iframe 2. Opens popup, uses wrong response type XSS 3. Loads sandbox iframe, URL 
 of main window is transferred 4. Sandbox XSS to sandbox on Reddit: frames[0].eval(..)
  46. PUBLIC XSS on sandbox/third-party domain getting URL 100 1. Victim

    clicks link, XSS in sandbox iframe 5. Attacker got the token! 2. Opens popup, uses wrong response type XSS 3. Loads sandbox iframe, URL 
 of main window is transferred 4. Sandbox XSS to sandbox on Reddit: frames[0].eval(..)
  47. PUBLIC Using APIs to fetch URL out-of-bounds 102 • URL

    is sent somewhere else but we will try to get it
  48. PUBLIC Using APIs to fetch URL out-of-bounds 103 • URL

    is sent somewhere else but we will try to get it • Such a fun bug, so many possibilities
  49. PUBLIC Using APIs to fetch URL out-of-bounds 104 • URL

    is sent somewhere else but we will try to get it • Such a fun bug, so many possibilities • There will be more alterations of this
  50. PUBLIC Using APIs to fetch URL out-of-bounds 105 • URL

    is sent somewhere else but we will try to get it • Such a fun bug, so many possibilities • There will be more alterations of this • Complex flow to explain, hang in there!
  51. PUBLIC Using APIs to fetch URL out-of-bounds 107 1. Victim

    clicks link, loads chat widget 2. Loads chat widget, 
 gets user’s API-token
  52. PUBLIC Using APIs to fetch URL out-of-bounds 108 1. Victim

    clicks link, loads chat widget 3. Opens popup 2. Loads chat widget, 
 gets user’s API-token
  53. PUBLIC Using APIs to fetch URL out-of-bounds 109 1. Victim

    clicks link, loads chat widget 3. Opens popup, uses wrong response type 2. Loads chat widget, 
 gets user’s API-token
  54. PUBLIC Using APIs to fetch URL out-of-bounds 110 1. Victim

    clicks link, loads chat widget 3. Opens popup, uses wrong response type 4. Loads sandbox iframe, 
 current URL is transferred 
 to Chat API 2. Loads chat widget, 
 gets user’s API-token
  55. PUBLIC Using APIs to fetch URL out-of-bounds 111 1. Victim

    clicks link, loads chat widget 3. Opens popup, uses wrong response type 4. Loads sandbox iframe, 
 current URL is transferred 
 to Chat API 2. Loads chat widget, 
 gets user’s API-token 4. Attacker polls API using token for 
 current URL
  56. PUBLIC Using APIs to fetch URL out-of-bounds 112 1. Victim

    clicks link, loads chat widget 5. Attacker got the token! 3. Opens popup, uses wrong response type 4. Loads sandbox iframe, 
 current URL is transferred 
 to Chat API 2. Loads chat widget, 
 gets user’s API-token 4. Attacker polls API using token for 
 current URL
  57. PUBLIC Conclusions 117 • Do NOT include third party scripts

    on error pages involved in the OAuth-dance 

  58. PUBLIC Conclusions 118 • Do NOT include third party scripts

    on error pages involved in the OAuth-dance 
 • Test the non-happy paths in OAuth yourself. 
 Is GTM loaded in this flow? 

  59. PUBLIC Conclusions 119 • Do NOT include third party scripts

    on error pages involved in the OAuth-dance 
 • Test the non-happy paths in OAuth yourself. 
 Is GTM loaded in this flow? 
 • OAuth-providers should allow turning off response- modes/types not being used