As you can see, the series is structured in an [Overview], attacks with concrete examples categorized as [Implementation] flaws and [Specification] flaws, and finally lessons learned during the [Responsible Disclosure].
Note that this post gives detailed insights into the Login Confusion attack.
The following post requires basic knowledge about OpenID Connect 1.0 (OIDC) and OAuth 2.0.
In general, three parties interact during an authentication process using OIDC:
The Service Provider (SP) that wants to provide a service to End-Users.
The OpenID Provider or Identity Provider (IdP) that authenticates the End-User for the Service Provider.
The End-User that authenticates to the Service Provider using an existing account at the Identity Provider.
Service Providers often support multiple authentication mechanisms, for example, using “native” accounts that have dedicated credentials and are managed by the SP or alternatively using “SSO” accounts that are registered at an Identity Provider (e.g., Google, Twitter, Github, …).
The Service Provider needs to be vulnerable to Login Cross-Site-Request-Forgery (CSRF), i.e., there is an endpoint that launches an OpenID Connect (OIDC) flow with a pre-configured Identity Provider. There are two common cases regarding OpenID Connect 1.0 implementations that fulfill this prerequisite:
Login Initiation Endpoint: The specification  defines a third-party Login Initiation Endpoint that serves as an intentional CSRF protection bypass as pointed out by Fett et al. in .
Non-normative External Login Endpoint: Some Service Providers implement internal endpoints that are used to start an OIDC login flow.
We present a generic Login CSRF flow in the following:
The Service Provider needs to implement a non-normative parameter that holds the redirection target after a successful login (commonly named nextUrl, url, next_url, …).
Additionally, session relevant relative paths like the Login Initiation Endpoints can be specified as destination after login.
The victim has two accounts at the Service Provider: One “native” account to which she authenticates using credentials (denoted as user A in the following) and one “SSO” account which is linked to an account on an external Identity Provider (denoted as user B in the following). Furthermore, the victim has an active session at the Identity Provider.
A generic Login Confusion flow is presented in the following:
If the previously outlined prerequisites are met, the following steps can be performed:
The victim requests the Login UI: https://sp.com/?next=/oauth/start. As one can observe, the next parameter holds the relative path of the Login Initiation Endpoint.
The victim authenticates through the Login UI with credentials for user A.
After successful authentication, the victim is redirected to the next URL (Login Initiation Endpoint): https://sp.com/oauth/start.
Without further interaction, the Login Initiation Endpoint starts a new OpenID Connect flow with the pre-configured Identity Provider including a valid state that is issued by the Service Provider.
Since the victim has an active session for user B on the Identity Provider, it immediately redirects the victim to the redirect_uri. This redirect includs the code and the state.
The Service Provider completes the OpenID Connect flow by redeeming the code at the Token Endpoint. As it receives an id_token for user B from the Identity Provider, user B is logged in at the Service Provider. As a result, the victim is now authenticated as user B, even though she entered her credentials for user A and did not perform any additional user interactions.
For our test environment, we use the official Docker image available at https://hub.docker.com/r/atlassian/bitbucket-server/.
Additionally, we need to set up our instance with a “Data Center” license, as the required “SSO 2.0” configuration would not be available in case we use a “Server” license. Finally, we require that the Bitbucket instance has a (secondary) OpenID Connect Identity Provider configured (Bitbucket can be configured to either only support authentication using OIDC or using OIDC as secondary authenticator with credentials as primary alternative method).
For our victim, we require that the victim browses an attacker-controlled website. Prerequisites for this attack are that the victim has two accounts at Bitbucket. For user A our victim uses credentials. User B is authenticated using an external Login Provider. Additionally, the victim has an active session at the Identity Provider.
Steps to Reproduce
Bitbucket implements two endpoints that enable intentional login CSRF. Both endpoints do not implement CSRF mitigations so that with a request to https://bitbucket.test/plugins/servlet/oidc/initiate-login or https://bitbucket.test/plugins/servlet/external-login an OpenID Connect login flow is started. If a user has an active session at the Identity Provider and previously gave consent to share information with Bitbucket as Service Provider, the Identity Provider immediately responds with the Authentication Response when the Authentication Endpoint is queried.
Furthermore, both endpoints allow GET parameters that specify where the user should be redirected to after successful authentication. While this parameter is sanitized to prevent Covert Redirects to external destinations, any path of the Bitbucket instance is allowed as a final destination, including session-related endpoints like the Logout Endpoint (that terminates the user’s session) or the Single Sign-On Login Initiation Endpoint. This sanitization enables the following Login Confusion attack:
Prerequisite (recall): The victim has an active session at the Identity Provider and previously used this account to authenticate as user B at Bitbucket.
Bitbucket serves a regular Login Form, the victim authenticates using her credentials for user A (1).
After successful authentication, Bitbucket redirects the victim to the Login Initialization Endpoint, as this was the previously provided destination (2).
Bitbucket receives the GET request to the Login Initiation Endpoint and launches a new OpenID Connect Login flow accordingly.
The victim has, per our prerequisites, an active session at the Identity Provider. As a result, there is a silent redirect with the Authentication Response to the redirect_uri endpoint including valid code and state parameters.
Bitbucket validates the state and redeems the code at the Identity Provider’s Token Endpoint. The Identity Provider responds with an id_token and access_token.
After validating the identity of user B, the victim is logged in as user B, although she entered her credentials for user A and did not perform any additional interactions.
To conclude the previous steps: The victim authenticates using credentials for user A but is then logged in as user B after multiple intransparent redirects and without further user interaction. This underlines the conclusion Fett et al. [1, Section III;A. 7)] drew in 2017: Endpoints that provide OpenID Connect related functionality require Cross-Site-Request-Forgery protection.
The following video demonstrates the Login Confusion issue present in Bitbucket.
Note that in the above video the native account isuserBand the SSO account isuserA.
The above-described behavior has a direct effect on the End-User’s session, does not require any privileges, and leads to an unforeseen login status from the End-User’s perspective.
If an End-User does not observe that the finally authenticated account is not the intended account, the End-User may perform actions with the wrong account that could, for example, leak their SSO Identity to third parties.
The impact is limited by the fact, that both accounts are under the control of the victim. The attacker cannot log in a victim into an attacker-controlled account, unless the Identity Provider has further flaws.
The Login Initiation Endpoint and External Login Endpoints should be removed entirely to mitigate this behavior. Alternatively, token- or referrer-based CSRF mitigations should be implemented. Furthermore, endpoints that have effects on the session should be entirely excluded from target_link_uri and next parameters, as a silent request to these endpoints has unforeseen effects on the current user session and the application’s behavior.
Atlassian’s triage process on Bugcrowd is very transparent. Their Security Team outlined that the above-described behavior is “intended behavior”. The report’s status was changed to “won’t fix” accordingly.
During direct communication with Atlassian’s security team using mail, they allowed using Bitbucket as an example in this blog post.
2020-08-18: Atlassian’s Security Team informs us that they reviewed the follow-up but still consider the report as “not applicable” regarding their policy:
I’m still not able to find the vulnerable component in the workflow. The scenario you described can happen with any IdP, this is not specific to bitbucket.
2020-09-21: Security team agrees on publishing this blog post:
Yes, please feel free to discuss those findings in your blog post. As you mentioned (and as was discussed in those submissions), we’ve determined each of those issues fall outside of our security model for Bitbucket Data Center and therefore will not be addressed.
Note that not every Service Provider is vulnerable to Login Confusion and that the countermeasures are quite trivial to implement, as presented within this post.
Thank you for reading this post! Stay tuned for the following posts of this series, as they will include more examples and detailed explanations of vulnerabilities that were found within popular real-life OpenID Connect Implementations.
If you have any feedback, feel free to contact me on Twitter: @_lauritz_. 👨💻
You can directly tweet about this post using this link. 🤓