Shopware: Timing-attack on admin panel allowing enumeration of administrator usernames
Description
Summary
There is a Proof of Concept which is able to enumerate the usernames of administrator users. This was possible by performing a timing attack.
Details
The faulty code exists in `src/Core/Framework/Api/OAuth/UserRepository.php`: `` public function getUserEntityByUserCredentials( string $username, #[\SensitiveParameter] string $password, string $grantType, ClientEntityInterface $clientEntity ): ?UserEntityInterface { if ($this->loginConfigService->getConfig()?->useDefault === false) { // never allow login via password if the default login is disabled (e.g. using SSO only) return null; } $builder = $this->connection->createQueryBuilder(); $user = $builder->select('user.id', 'user.password') ->from('user') ->where('username = :username') ->setParameter('username', $username) ->fetchAssociative(); // PATH 1: EARLY RETURN WHEN USERNAME IS NOT FOUND if (!$user) { return null; } // PATH 2: VERIFY PASSWORD IF USER IS FOUND if (!password_verify($password, (string) $user['password'])) { return null; } return new User(Uuid::fromBytesToHex($user['id'])); } ``
Subroutine getUserEntityByUserCredentials() is called when an auth request is send to api/oauth/token. If the given username is not found an early return is done (PATH 1). Only if the user is found we verify the password using password_verify.
PHP method password_verify by default uses hashing algorithm Argon2id which by design is intentionally 'slow' by introducing a timing cost to an attempt to bruteforce hashes more costly.
Since password_verify has a notable executable time, PATH 2 where an user is found and verified will be slower on average then PATH 1 where we do an early return for non-existing users.
Proposed fix
Before doing the early return, password_verify a dummy hash.
### Impact 1. More targeted dictionary/bruteforce attacks. 2. Spear phishing / eases social engineering. 3. Credential stuffing from other data leaks.
Authors
Niel Duysters (@NielDuysters) and Thomas Brankaer (@tbrankaer)
Affected products
1Patches
0No patches discovered yet.
Vulnerability mechanics
Root cause
"The timing difference between handling existing and non-existing usernames allows for username enumeration."
Attack vector
An attacker can send authentication requests to the `api/oauth/token` endpoint with various usernames. If a username exists, the application proceeds to password verification, which takes longer due to the `password_verify` function. If the username does not exist, the application returns early, resulting in a shorter execution time. By measuring these timing differences, an attacker can distinguish between valid and invalid usernames, enabling username enumeration [ref_id=1].
Affected code
The vulnerability resides in the `getUserEntityByUserCredentials` function within the file `src/Core/Framework/Api/OAuth/UserRepository.php`. Specifically, the code first checks if a user exists by querying the database. If the user is not found, it returns early (PATH 1). If the user is found, it then proceeds to verify the password using `password_verify` (PATH 2) [ref_id=1].
What the fix does
The proposed fix involves calling `password_verify` with a dummy hash before the early return for non-existent users. This ensures that both paths (user found and user not found) have a similar execution time, mitigating the timing difference that enabled the username enumeration attack. By equalizing the execution time, the vulnerability is resolved [ref_id=1].
Preconditions
- networkThe attacker must be able to send requests to the `api/oauth/token` endpoint.
- inputThe attacker needs to be able to provide a username and a password (or any password) to the authentication request.
Generated on Jun 4, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
1- Shopware: Nine Vulnerabilities Disclosed, Including Privilege Escalation and XSSVypr Intelligence · Jun 4, 2026