Not logged in

V1: True Pre-Hijacking High

Attacker registers with the victim's email before the victim does. The victim's own SSO login then activates the attacker's account. Both end up sharing the same account.

/auth/sso/callback
// /auth/sso/callback router.get('/auth/sso/callback', async (req, res) => { const { email, provider } = parseOAuthToken(req.query.code) const user = await db.users.findByEmail(email) if (user) { // BUG: no check on who created this account or whether this provider // was ever associated with it. An attacker who pre-registered with // this email (before the real owner) gets their account activated // by the victim's own sign-in action. await db.users.update(user.id, { emailVerified: true, ssoProviders: [...user.ssoProviders, provider], }) return createSession(res, user.id) } const newUser = await db.users.create({ email, emailVerified: true, ssoProviders: [provider] }) createSession(res, newUser.id) })

1

Attacker: register with victim's email attacker

Register with the target email and any password. Do not click the verification link that appears.

Password will be set to Password123

2

Victim: signs in via SSO victim

The victim discovers the service and uses SSO. They have never registered before. Use the same email as step 1.

3

Attacker: log in with original password attacker

Log out the victim session above, then log in as the attacker. Both parties now share the same account.

Using password Password123