SUBMISSION 2
TITLE: User Email Enumeration via /v1/userauth Error Message and Timing Difference
TARGET: api.aiven.io (https://api.aiven.io/login)
VRT CATEGORY: Broken Authentication and Session Management > Username/Email Enumeration > Non-Brute Force
URL: https://api.aiven.io/v1/userauth
DESCRIPTION:
Summary
The login endpoint POST /v1/userauth returns different error messages and response times for registered vs unregistered email addresses, enabling unauthenticated user enumeration.
- Non-existent email:
"User does not exist", ~150ms response - Existing email:
"user_password_compromised", ~2,500-5,200ms response
The dual oracle (message + timing) makes enumeration highly reliable. Notably, the password reset endpoint (/v1/user/password_reset_request) is properly implemented and returns a uniform response regardless of email existence.
Steps to Reproduce
- Send a request with a non-existent email:
curl -s -w "\nTime: %{time_total}s" -X POST https://api.aiven.io/v1/userauth \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"test123"}'
Response: HTTP 403, ~150-477ms
{"errors":[{"message":"User does not exist","status":403}]}
- Send a request with a known existing email:
curl -s -w "\nTime: %{time_total}s" -X POST https://api.aiven.io/v1/userauth \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"wrongpassword123!"}'
Response: HTTP 403, ~5,225ms
{"errors":[{"error_code":"user_password_compromised","message":"Your login is blocked because your password is no longer safe. Reset your password to log in.","status":403}]}
- Additional tests confirming the pattern:
| Message | Time | Exists? | |
|---|---|---|---|
| [email protected] | “User does not exist” | ~150ms | No |
| [email protected] | “user_password_compromised” | ~5,225ms | Yes |
| [email protected] | “user_password_compromised” | ~2,688ms | Yes |
| [email protected] | “User does not exist” | ~150ms | No |
Impact
An attacker can determine which email addresses are registered on Aiven. This enables targeted credential stuffing against confirmed accounts and targeted phishing campaigns impersonating Aiven (e.g., fake password reset emails). The 10-35x timing difference makes automated enumeration reliable even if error messages were normalized.
Root Cause
The API checks email existence before password validation and returns distinct error messages. The timing difference is likely caused by an additional breach database (HIBP) lookup that only occurs for existing accounts.
Suggested Fix
Return a generic "Invalid credentials" message for all authentication failures and normalize response timing.
Source · github.com/zionsworking/security-research-notebook · writeups/aiven/email-enumeration-timing.md