Account takeover via misconfigured SSO [OIDC] implementation

How we got there

A story about how an OIDC login provider without email confirmation allowed me takeover accounts on a different web app.

This was on a particular friday evening after reading an interesting writeup about Oauth security issues that lead to account takeover, i decided to test the new knowledge on a target i had seen supported Oauth2 login. My target lets call it xboy.me was intersting as it had a few applications in scope, lets call them court-app.xboy.me and tennis-app.xboy.me. Now court-app.xboy.me supported various Oauth2 methods like google, etc. However tennis-app.xboy.me had only two login options (1) username/email and password via Cognito (2) Oauth2 OIDC [from court-app.xboy.me] via Cognito.

OIDC = OpenID Connect (OIDC) is an identity layer built on top of the OAuth 2.0 framework. It allows third-party applications to verify the identity of the end-user and to obtain basic user profile information. OIDC uses JSON web tokens (JWTs), which you can obtain using flows conforming to the OAuth 2.0 specifications. by https://auth0.com/docs/authenticate/protocols/openid-connect-protocol#:~:text=OpenID%20Connect%20(OIDC)%20is%20an,to%20the%20OAuth%202.0%20specifications.

The web application at https://court-app.xboy.me/ uses custom user authentication/registration which allows users to signup/register accounts and use them without email activation/confirmation, while https://tennis-app.xboy.me uses AWS cognito, which ensures users confirm their emails before using the account. The web app https://tennis-app.xboy.me also uses Oauth2 (OIDC) from https://court-app.xboy.me/ which as i said allows unverified users to use the web app.

Heres how the tennis-app.xboy.me OIDC flow goes

user goes to https://tennis-app.xboy.me => clicks login via oauth => https://tennis-app.xboy.me oauth request to https://tennis-app.auth.us-west-1.amazoncognito.com/oauth2/authorize => gets redirected to https://court-app.xboy.me/oauth2/authenticate => gets redirected to https://court-app.xboy.me/api/oauth2/authorize? => https://tennis-app.xboy.me/oauth2? => gets redirected to https://court-app.xboy.me/oauth2/idpresponse? => gets redirected to => https://tennis-app.auth.us-west-1.amazoncognito.com/oauth2/idpresponse? => gets redirected to https://tennis-app.xboy.me/oauth/success? => https://tennis-app.auth.us-west-1.amazoncognito.com/oauth2/token [post request to get access token]

What goes on

When a user clicks on login via court-app the flow fetches the required token and info from court-app and everything is well and expected. However instead of logging in the user directly an account is created with the court-app details and this account is not the same as the one we need to takeover. However a weird behaviour happens.

The weird behaviour

Ater a successful account creation with court-app details, the https://tennis-app.xboy.me web app sends a post request https://tennis-app.xboy.me/api/token/refresh with the idToken param containing the jwt created after the account creation.

This is where things go really wrong really fast as we get logged out for a momment and before we know it we get logged in as the victim.

This is due to a misconfigured OIDC [i believe] it takes in a few params including a JWT TOKEN Created by the oauth2 follow.

Reproduction Steps

The attack goes as follows;

So basically the takeover works as flows, User is registered at https://tennis-app.xboy.me only and not https://court-app.xboy.me/ => We (attacker) register at https://court-app.xboy.me/ => after successfull registration (no email verification) we go to https://tennis-app.xboy.me and select the Oauth2 (OIDC) login option and we get logged into the victim account after a moment

i.e user registers at https://tennis-app.xboy.me with "root@xboy.me" and password "#sup3rs3cur3P4ss$", confirms account and starts to use it, as attackers we just head to https://court-app.xboy.me/ and register an account with "root@xboy.me" and password "#@Password-1234" but we don't need to confirm the email. we then head to https://tennis-app.xboy.me and select the Oauth2 (OIDC) login option and we get wait for the accounts to be merged

Reproduction is as simple as;

  1. Go to https://tennis-app.xboy.me and create an account with an email not registered at https://court-app.xboy.me
  2. Log out on completion
  3. Go to https://court-app.xboy.me and create an account with the above email and finish the set up [wont ask for verification]
  4. Head back to https://tennis-app.xboy.me and click login with court-app observe the flow and at the end you have you account takeover

Report

I quickly made a detailed report with as much explanation as i could and submitted. report got triaged in less than two hours as a critical and got awarded €€€€ bounty.

basic

Contacts

@github @twitter @LinkedIn @Intigriti @hackerone_old

🔥🔥: 0

Previous Post

AuthBypass

Next Post

AWSTakeover