GHSA-7W52-7JVM-M9VW
Vulnerability from github – Published: 2026-06-04 19:31 – Updated: 2026-06-04 19:31Summary
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
- More targeted dictionary/bruteforce attacks.
- Spear phishing / eases social engineering.
- Credential stuffing from other data leaks.
Authors
Niel Duysters (@NielDuysters) and Thomas Brankaer (@tbrankaer)
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "shopware/platform"
},
"ranges": [
{
"events": [
{
"introduced": "6.7.0.0"
},
{
"fixed": "6.7.10.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "shopware/platform"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "6.6.10.18"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "shopware/core"
},
"ranges": [
{
"events": [
{
"introduced": "6.7.0.0"
},
{
"fixed": "6.7.10.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "shopware/core"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "6.6.10.18"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-48011"
],
"database_specific": {
"cwe_ids": [
"CWE-208"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-04T19:31:17Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "### Summary\nThere is a Proof of Concept which is able to enumerate the usernames of administrator users. This was possible by performing a timing attack.\n\n### Details\nThe faulty code exists in [`src/Core/Framework/Api/OAuth/UserRepository.php`](https://github.com/shopware/shopware/blob/trunk/src/Core/Framework/Api/OAuth/UserRepository.php):\n```\npublic function getUserEntityByUserCredentials(\n string $username,\n #[\\SensitiveParameter]\n string $password,\n string $grantType,\n ClientEntityInterface $clientEntity\n ): ?UserEntityInterface {\n if ($this-\u003eloginConfigService-\u003egetConfig()?-\u003euseDefault === false) {\n // never allow login via password if the default login is disabled (e.g. using SSO only)\n return null;\n }\n\n $builder = $this-\u003econnection-\u003ecreateQueryBuilder();\n $user = $builder-\u003eselect(\u0027user.id\u0027, \u0027user.password\u0027)\n -\u003efrom(\u0027user\u0027)\n -\u003ewhere(\u0027username = :username\u0027)\n -\u003esetParameter(\u0027username\u0027, $username)\n -\u003efetchAssociative();\n\n // PATH 1: EARLY RETURN WHEN USERNAME IS NOT FOUND\n if (!$user) {\n return null;\n }\n\n // PATH 2: VERIFY PASSWORD IF USER IS FOUND\n if (!password_verify($password, (string) $user[\u0027password\u0027])) {\n return null;\n }\n\n return new User(Uuid::fromBytesToHex($user[\u0027id\u0027]));\n }\n```\n\nSubroutine `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`.\n\nPHP method `password_verify` by default uses hashing algorithm Argon2id which by design is intentionally \u0027slow\u0027 by introducing a timing cost to an attempt to bruteforce hashes more costly.\n\nSince `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.\n\n### Proposed fix\nBefore doing the early return, `password_verify` a dummy hash.\n\n### Impact\n1. More targeted dictionary/bruteforce attacks.\n2. Spear phishing / eases social engineering.\n3. Credential stuffing from other data leaks.\n\n### Authors\nNiel Duysters (@NielDuysters) and Thomas Brankaer (@tbrankaer)",
"id": "GHSA-7w52-7jvm-m9vw",
"modified": "2026-06-04T19:31:17Z",
"published": "2026-06-04T19:31:17Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/shopware/shopware/security/advisories/GHSA-7w52-7jvm-m9vw"
},
{
"type": "PACKAGE",
"url": "https://github.com/shopware/shopware"
},
{
"type": "WEB",
"url": "https://github.com/shopware/shopware/releases/tag/v6.6.10.18"
},
{
"type": "WEB",
"url": "https://github.com/shopware/shopware/releases/tag/v6.7.10.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Shopware: Timing-attack on admin panel allowing enumeration of administrator usernames"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.