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 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.
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.meoauth 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://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.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.
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.mewith "firstname.lastname@example.org" 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 "email@example.com" and password "#@Password-1234" but we don't need to confirm the email. we then head to
https://tennis-app.xboy.meand select the Oauth2 (OIDC) login option and we get wait for the accounts to be merged
Reproduction is as simple as;
- Go to
https://tennis-app.xboy.meand create an account with an email not registered at
- Log out on completion
- Go to
https://court-app.xboy.meand create an account with the above email and finish the set up [wont ask for verification]
- Head back to
https://tennis-app.xboy.meand click login with
court-appobserve the flow and at the end you have you account takeover
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.