Exploiting Email Normalization and Custom Database Configurations in Auth0 for Account Takeover
Hey, I’m Hussam Ahmed — a security researcher with a strong focus on web application security. My specialty lies in authentication: from login flows and session handling to token logic, OAuth, and SSO — and the subtle ways these systems break.
I spend most of my time analyzing real-world authentication implementations, uncovering vulnerabilities through bug bounty programs, and digging into edge-case behaviors that often go unnoticed. If there’s an identity flow or token exchange in play, chances are — I’m already testing it.
<!-- Nykros -- >
Introduction
Authentication systems serve as the gatekeepers to user accounts and sensitive data. Ensuring their security is crucial to prevent unauthorized access, data breaches, and loss of user trust. Email normalization—the process of standardizing email addresses—plays a critical role in maintaining the integrity of these systems. Inconsistent handling of email normalization can inadvertently allow attackers to bypass security measures, leading to account duplication and unauthorized access.
This article examines a specific vulnerability identified during a penetration test on an application leveraging Auth0 for authentication, highlighting the critical role of email normalization in maintaining authentication integrity.
Application Overview
The application under test utilizes Auth0 to handle user authentication, offering two primary methods for account creation:
Sign Up with Google: Users can create an account using their Google credentials.
Email and Password: Users can register by providing an email address and a password.
Our focus is on the Email and Password registration method, as it interacts directly with Auth0's email handling and database configurations.
Initial Testing and Discovery
Replicating a Known Vulnerability
During an initial penetration test, a previously identified vulnerability was tested. By following the known exploit steps, an Account Takeover (ATO) was successfully achieved. Upon discovering this vulnerability, it was promptly reported to the client, and immediate actions were taken to fix the issue.
YOU can read the Write-up here: exploiting-auth0-misconfigurations-a-case-study-on-account-linking-vulnerabilities
Attempting Duplicate Account Creation
To further investigate, a new account was created using the email ihussam@xx.xx with the password PassOne123. An attempt to create another account with the same email but a different password using Auth0's public endpoint resulted in an error message: "Email already exists!" This behavior indicated that the system was correctly preventing duplicate email registrations through the standard UI and Auth0 Public Endpoint.
- Reason for Using the Public Endpoint and Default database connection I will explain the reason for such behavior in a separate write-up.
Understanding Email Normalization
Email normalization involves transforming email addresses into a standardized format to ensure consistency across various operations like registration, login, and data retrieval. Proper normalization helps in:
Preventing Duplicate Accounts: Ensures that variations of an email address (e.g., different cases, Unicode characters) don't result in multiple accounts for the same user.
Enhancing Security: Reduces the risk of account takeover through visually similar but technically distinct email addresses using Unicode characters.
Common Normalization Techniques
Unicode Normalization: Converts Unicode characters to a standard form using normalization forms like NFKC (Normalization Form Compatibility Composition).
Case Normalization: Converts the entire email address to lowercase to avoid case-sensitive discrepancies.
Dot Removal: Removes dots in specific email domains (e.g., Gmail) where dots are insignificant.
Exploitation of Email Normalization
Creating a Unicode Email Address
To bypass the "Email already exists!" restriction, an email address with a Unicode character was crafted: ıhussam@xx.xx (note the dotted dotless 'i'). This email was used with Auth0's public endpoint, allowing the creation of a new account with the credentials [ıhussam@xx.xx - AccTwo123].
Observing Auth0's Handling of Unicode Emails
Auth0 does not perform email normalization by default. As a result, it treated ıhussam@xx.xx as a different email from ihussam@xx.xx. This discrepancy allowed the creation of what appeared to be a separate account using a slightly altered email address.
Achieving Account Takeover
When logging into the newly created account with [ıhussam@xx.xx - AccTwo123], access was gained to the original account's data and documents. This indicated a successful Account Takeover. Conversely, attempting to log in with the original credentials [ihussam@xx.xx - PassOne123] resulted in an error stating that the password is wrong—a highly unusual and concerning behavior.

Technical Analysis: Auth0's Custom Database Configuration
Understanding Auth0's Custom Database Feature
Auth0 offers a Custom Database feature that allows developers to connect their own user databases with Auth0. This is achieved by linking an external database to an Auth0 database connection and creating custom scripts to handle user authentication processes.

Key Scripts in Custom Database Integration
Create User Script: Runs when a user tries to sign up. It takes the user's details (like email and password) and creates a new user entry in the external database.
Get User Script: Runs concurrently with the Create User script during the signup process. It checks if the provided email already exists in the external database before allowing a new account to be created.
Root Cause of the Vulnerability
The main issue lies in how these scripts handle email normalization:
Lack of Email Normalization in Get User Script: The
Get User Scriptdid not normalize the email. This means that emails with Unicode characters could bypass the initial check to see if the email already exists, allowing duplicate accounts to be created.Normalization in Create User Script: The
Create User Scriptdid normalize the email by converting Unicode characters to their ASCII equivalents. This caused the normalized email to match the original email in the database, leading to the overwriting of credentials and facilitating the Account Takeover.
It's important to highlight that the application also performs email normalization during the login process. This means that when a user attempts to log in, the input email is normalized in the same manner as during the registration process. The normalization involves converting Unicode characters to their ASCII equivalents and making all characters lowercase.
Simulating Vulnerable Scripts
Below are simulated versions of the Create User and Get User scripts used in Auth0's Custom Database configuration. These examples illustrate how improper handling of email normalization can introduce vulnerabilities, specifically allowing for Account Takeover (ATO).
Vulnerable Create User Script
This script incorrectly normalizes the email by converting Unicode characters to their ASCII equivalents. This normalization can inadvertently allow duplicate accounts or overwrite existing user credentials.
function create(user, callback) {
// Extract user details
const userEmail = user.email;
const userPassword = user.password;
// Vulnerable Email Normalization: Converts Unicode characters to ASCII
const normalizedEmail = userEmail.normalize('NFKC').toLowerCase();
// Example: Overwriting existing user if normalized email matches
database.findUserByEmail(normalizedEmail, (err, existingUser) => {
if (err) return callback(new Error('Database error'));
if (existingUser) {
// Vulnerability: Overwrites the existing user's password
database.updateUserPassword(existingUser.id, userPassword, (updateErr) => {
if (updateErr) return callback(new Error('Password update failed'));
return callback(null); // User creation successful (credentials overwritten)
});
} else {
// Create new user with normalized email
database.createUser(normalizedEmail, userPassword, (createErr) => {
if (createErr) return callback(new Error('User creation failed'));
return callback(null); // User creation successful
});
}
});
}
Vulnerability Explanation:
Email Normalization in Create User Script:
The script normalizes the email by converting it to its ASCII equivalent and making it lowercase.
Example:
ıhussam@xx.xxbecomesihussam@xx.xx.
Overwriting Existing Users:
If a user with the normalized email already exists, the script updates the existing user's password with the new password provided. {{But WHY?}}
This allows an attacker to overwrite another user's credentials by using a cleverly crafted email address with Unicode characters.
Vulnerable Get User Script
This script fails to normalize the email before checking for existing users. As a result, emails containing Unicode characters can bypass the existence check, allowing the creation of duplicate accounts.
function getByEmail(email, callback) {
// Extract the email provided during login/signup
const inputEmail = email;
// Vulnerable: No Email Normalization performed here
// Emails with Unicode characters are treated differently
// Attempt to find user by the raw input email
database.findUserByEmail(inputEmail, (err, user) => {
if (err) return callback(new Error('Database error'));
if (user) {
// User found, return the user profile
return callback(null, user);
} else {
// User not found, proceed to Create User Script
return callback(null);
}
});
}
Vulnerability Explanation:
Lack of Email Normalization in Get User Script:
The script uses the raw input email without any normalization.
This means that
ıhussam@xx.xxis treated as a different email fromihussam@xx.xx.
Bypassing Duplicate Checks:
An attacker can create an email with Unicode characters that visually resemble an existing user's email.
Since the
Get Userscript does not normalize the email, it does not recognize it as existing, allowing the attacker to create a new account with that email.Meanwhile, the
Create Userscript normalizes the email and may overwrite the original user's credentials, leading to Account Takeover.
Summary of the Vulnerability
Inconsistent Email Handling:
The Create User script normalizes emails, altering Unicode characters to their ASCII equivalents.
The Get User script does not normalize emails, allowing Unicode variations to bypass user existence checks.
Exploitation Path:
Step 1: Attacker registers a new account using an email with Unicode characters that normalize to an existing user's email.
Step 2: The Get User script does not recognize the normalized email, allowing the creation of a seemingly new account.
Step 3: The Create User script normalizes the email and overwrites the existing user's credentials with the attacker's password.
Result: The attacker gains access to the original user's account data, achieving Account Takeover.
Stay Secure!
If you found this article helpful, feel free to share it.
LinkedIn: Hossam Ahmed