Intro: Cloud Pentesting and the Shared Responsibility Model
Username enumeration vulnerabilities can allow attackers to identify valid users, which is the first step in many attacks. During a recent pentest, we discovered two username enumeration vulnerabilities in the AWS Web Console. These vulnerabilities are interesting as they reside on AWS’s side of the Shared Responsibility Model. A majority of our testing and research focuses on the Customer’s side of the model or “Security in the Cloud”.
The two username enumeration findings we’ll detail here, result from bugs in Amazon’s credential verification software and put all console-enabled IAM users at risk of username enumeration.
As every AWS customer was affected by these risks, AWS worked closely with Rhino to get these addressed promptly.
Note: While this article is a walkthrough of 2 findings related to username enumeration, only one has a CVE (Finding 2) and was acknowledged by AWS as a security flaw. Amazon noted that Finding 1 was an “Accepted Risk”.
Finding 1 - Username Enumeration (Users w/ MFA)
When MFA is enabled for an IAM user account, the login flow discloses the user’s existence. The flow diagram below shows the user experience of the login flow. After submitting credentials there is a fork that produces two completely different application states in the UI. This doesn’t require any special tools to detect.
If the user exists (regardless of whether the password is correct), the next page requests an MFA code (top image), confirming the IAM user in AWS.
Otherwise, the application displays an error message that the user does not exist (bottom image).
While this isn’t uncommon to see in web applications, its surprising to find in one of the major cloud providers.
Finding 2 (CVE-2025-0693) - Username Enumeration via Timing Attack (no MFA)
Finding 1 relies on the target IAM user having MFA enabled, which is an optional security feature – not all users use MFA. For those that don’t, the login flow is slightly different, and contains no obvious enumeration flaws.
However, when looking closely at the traffic with a web proxy (Burp Suite), we noticed an interesting behavior that we could leverage for user enumeration. The login flow for this case is pictured below –
When a single-factor (non-MFA) user submits credentials, there are two possible responses: “Error” and “Logged In”. Simulating an attacker, we don’t have the user’s password yet, so let’s look at the paths to Error.
Generally, login flows must validate both the username and password. If the user exists, the password gets checked. This check takes time and may result in a slower response from the server. If the timing difference is measurable it can be used for username enumeration.
To check for a timing difference, we created a test IAM user in our AWS account with the username “bfme-console”. The user was granted console access and MFA was disabled. We then used Burp Suite’s Intruder with no concurrency (Resource Pool > Maximum Concurrent Requests “1”). Below is an image of the Intruder results. The columns in the screenshot are:
- Request: The request’s index. Sorting by this column will organize the list chronologically.
- Payload: The payload used in the request. In this case, the payload is a username.
- Status code: The HTTP status code received from the server.
- Response received: The number of milliseconds it took for the server to respond. This is the key column here, as it is the closest representation of how long the server took to reply.
Looking at the results in chronological order, we see a ~100ms increase in response time for the known test user. The timing difference is too small for humans to notice, but by measuring the precise response time, we can infer the logical path taken for the given user.
Preventing Authentication Timing Attacks
The key to preventing these types of enumeration attacks is to ensure the server behaves the same when the username is valid or invalid. The likely cause of the timing difference is something known as a “quick exit” – a logical shortcut in the code often taken for efficiency’s sake. The OWASP Authentication Cheat Sheet describes this well and provides a pseudo-code comparison of a vulnerable and secure implementation of authentication failure.
The first code block below is insecure, containing a bug similar to the one disclosed here. Notice that the code jumps to the ELSE block if the user does not exist, displaying an error with much less processing (and time).
IF USER_EXISTS(username) THEN password_hash=HASH(password) IS_VALID=LOOKUP_CREDENTIALS_IN_STORE(username, password_hash) IF NOT IS_VALID THEN RETURN Error("Invalid Username or Password!") ENDIF ELSE RETURN Error("Invalid Username or Password!") ENDIF
This next code block (also from the Authentication Cheat Sheet) shows us how to avoid the timing difference by ensuring both cases take the same amount of processing, and thus a similar amount of time.
password_hash=HASH(password) IS_VALID=LOOKUP_CREDENTIALS_IN_STORE(username, password_hash) IF NOT IS_VALID THEN RETURN Error("Invalid Username or Password!") ENDIF
Logging / Detection of CVE-2025-0693
Both attacks disclosed here generate “ConsoleLogin” events in CloudTrail, one with errorMessage “No username found in supplied account” and the other “Failed Authentication” (when username is valid but mfa or password is incorrect). Screenshots below provide the full Cloudtrail Log for each (Left: invalid IAM usernames, Right: valid usernames w/ failed authentication).
Large numbers of these two CloudTrail events (particularly from a range of IPs, or over a long period) may indicate your organization had been targeted using one – or both – of these techniques.
Conclusion
In this blog post, we covered two username enumeration flaws on the AWS Console Login page (including CVE-2025-0693).
We also discussed how one finding2 (CVE-2025-0693) was patched, but finding 1 was considered an “accepted risk”. Potential remediations for this issue was provided, and specifically what to look for in CloudTrail logs.
We’d like to extend a big “thank you” to the AWS Security team for their timely replies and for working with us to get this issue patched for all AWS customers.
Vulnerability Disclosure Timeline
Date | Event |
9/16/2024 | Disclosed vulnerabilities to AWS |
9/30/2024 | AWS acknowledged the timing-based vulnerability (Finding 2) and will be issuing a CVE |
1/23/2025 | Finding 2 issued CVE-2025-0693 |
1/23/2025 | AWS patched CVE-2025-0693 |
1/30/2025 | AWS confirmed they are aware of Finding 1 (username enumeration of users w/ MFA), and accept the risk. No CVE issued. |