Craft Commerce: Coupon Code Brute-Force via Rate Limit Bypass
The advisory, in context
Summary
The CartController defines a RateLimiter behavior that is only activated when the 'number' POST/GET parameter is explicitly provided.
Details
When an attacker submits coupon codes against the session-based cart (without passing a 'number' parameter), no rate limiting is applied. This allows unlimited attempts to guess coupon codes.
Vulnerable Code <img width="864" height="90" alt="resim" src="https://github.com/user-attachments/assets/a5197f10-f1fd-4331-93f9-9479d0ceebba" />
<img width="881" height="272" alt="resim" src="https://github.com/user-attachments/assets/d9db963f-5d1f-4b00-a4b4-5f2dfe2b71dd" />
<img width="861" height="271" alt="resim" src="https://github.com/user-attachments/assets/f7842493-3bc0-4e99-956c-7266bab15703" />
PoC
Complete instructions, including specific configuration details, to reproduce the vulnerability.
<img width="909" height="171" alt="resim" src="https://github.com/user-attachments/assets/cfc8c994-5e0c-48de-b728-464029beba0e" />
Impact
An attacker can enumerate all coupon codes through automated requests.
Remediation Apply rate limiting unconditionally on actionUpdateCart regardless of whether 'number' is present.
Affected packages
Start with the recorded fix for your release branch. Check your installed version and test compatibility before upgrading. Fixing this advisory does not rule out other vulnerabilities in the release.
From 5.0.0 before 5.6.5
Fixed in 5.6.5
95 explicitly affected versions
5.0.0, 5.0.1, 5.0.10, 5.0.10.1, 5.0.11, 5.0.11.1, 5.0.12, 5.0.12.1, 5.0.12.2, 5.0.13, 5.0.14, 5.0.15, 5.0.16, 5.0.16.1, 5.0.16.2, 5.0.17, 5.0.18, 5.0.19, 5.0.2, 5.0.3, 5.0.4, 5.0.5, 5.0.6, 5.0.7, 5.0.8, 5.0.9, 5.1.0, 5.1.0-beta.1, 5.1.0-beta.2, 5.1.0-beta.3, 5.1.0.1, 5.1.1, 5.1.2, 5.1.3, 5.1.4, 5.2.0, 5.2.1, 5.2.10, 5.2.11, 5.2.12, 5.2.12.1, 5.2.2, 5.2.2.1, 5.2.3, 5.2.4, 5.2.5, 5.2.6, 5.2.7, 5.2.8, 5.2.9, 5.2.9.1, 5.3.0, 5.3.0.1, 5.3.0.2, 5.3.1, 5.3.10, 5.3.11, 5.3.12, 5.3.13, 5.3.2, 5.3.2.1, 5.3.2.2, 5.3.3, 5.3.4, 5.3.5, 5.3.6, 5.3.7, 5.3.8, 5.3.9, 5.4.0, 5.4.1, 5.4.1.1, 5.4.10, 5.4.2, 5.4.3, 5.4.4, 5.4.5, 5.4.5.1, 5.4.6, 5.4.7, 5.4.7.1, 5.4.8, 5.4.9, 5.5.0, 5.5.0.1, 5.5.1, 5.5.2, 5.5.3, 5.5.4, 5.6.0, 5.6.1, 5.6.1.1, 5.6.2, 5.6.3, 5.6.4
View affected-version evidence
{
"ranges": [
{
"events": [
{
"introduced": "5.0.0"
},
{
"fixed": "5.6.5"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"5.0.0",
"5.0.1",
"5.0.10",
"5.0.10.1",
"5.0.11",
"5.0.11.1",
"5.0.12",
"5.0.12.1",
"5.0.12.2",
"5.0.13",
"5.0.14",
"5.0.15",
"5.0.16",
"5.0.16.1",
"5.0.16.2",
"5.0.17",
"5.0.18",
"5.0.19",
"5.0.2",
"5.0.3",
"5.0.4",
"5.0.5",
"5.0.6",
"5.0.7",
"5.0.8",
"5.0.9",
"5.1.0",
"5.1.0-beta.1",
"5.1.0-beta.2",
"5.1.0-beta.3",
"5.1.0.1",
"5.1.1",
"5.1.2",
"5.1.3",
"5.1.4",
"5.2.0",
"5.2.1",
"5.2.10",
"5.2.11",
"5.2.12",
"5.2.12.1",
"5.2.2",
"5.2.2.1",
"5.2.3",
"5.2.4",
"5.2.5",
"5.2.6",
"5.2.7",
"5.2.8",
"5.2.9",
"5.2.9.1",
"5.3.0",
"5.3.0.1",
"5.3.0.2",
"5.3.1",
"5.3.10",
"5.3.11",
"5.3.12",
"5.3.13",
"5.3.2",
"5.3.2.1",
"5.3.2.2",
"5.3.3",
"5.3.4",
"5.3.5",
"5.3.6",
"5.3.7",
"5.3.8",
"5.3.9",
"5.4.0",
"5.4.1",
"5.4.1.1",
"5.4.10",
"5.4.2",
"5.4.3",
"5.4.4",
"5.4.5",
"5.4.5.1",
"5.4.6",
"5.4.7",
"5.4.7.1",
"5.4.8",
"5.4.9",
"5.5.0",
"5.5.0.1",
"5.5.1",
"5.5.2",
"5.5.3",
"5.5.4",
"5.6.0",
"5.6.1",
"5.6.1.1",
"5.6.2",
"5.6.3",
"5.6.4"
]
}From 4.0.0 before 4.11.2
Fixed in 4.11.2
73 explicitly affected versions
4.0.0, 4.0.1, 4.0.2, 4.0.3, 4.0.4, 4.1.0, 4.1.1, 4.1.2, 4.1.3, 4.10.0, 4.10.1, 4.10.2, 4.11.0, 4.11.0.1, 4.11.1, 4.2.0, 4.2.1, 4.2.10, 4.2.11, 4.2.2, 4.2.3, 4.2.4, 4.2.5, 4.2.5.1, 4.2.6, 4.2.7, 4.2.8, 4.2.9, 4.3.0, 4.3.1, 4.3.2, 4.3.3, 4.4.0, 4.4.1, 4.4.1.1, 4.5.0, 4.5.1, 4.5.1.1, 4.5.2, 4.5.3, 4.5.4, 4.6.0, 4.6.1, 4.6.10, 4.6.11, 4.6.12, 4.6.13, 4.6.14, 4.6.2, 4.6.3.1, 4.6.4, 4.6.5, 4.6.6, 4.6.7, 4.6.8, 4.6.9, 4.7.0, 4.7.1, 4.7.2, 4.7.3, 4.8.0, 4.8.0.1, 4.8.1, 4.8.1.1, 4.8.1.2, 4.8.2, 4.8.3, 4.8.4, 4.9.0, 4.9.1, 4.9.2, 4.9.3, 4.9.4
View affected-version evidence
{
"ranges": [
{
"events": [
{
"introduced": "4.0.0"
},
{
"fixed": "4.11.2"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"4.0.0",
"4.0.1",
"4.0.2",
"4.0.3",
"4.0.4",
"4.1.0",
"4.1.1",
"4.1.2",
"4.1.3",
"4.10.0",
"4.10.1",
"4.10.2",
"4.11.0",
"4.11.0.1",
"4.11.1",
"4.2.0",
"4.2.1",
"4.2.10",
"4.2.11",
"4.2.2",
"4.2.3",
"4.2.4",
"4.2.5",
"4.2.5.1",
"4.2.6",
"4.2.7",
"4.2.8",
"4.2.9",
"4.3.0",
"4.3.1",
"4.3.2",
"4.3.3",
"4.4.0",
"4.4.1",
"4.4.1.1",
"4.5.0",
"4.5.1",
"4.5.1.1",
"4.5.2",
"4.5.3",
"4.5.4",
"4.6.0",
"4.6.1",
"4.6.10",
"4.6.11",
"4.6.12",
"4.6.13",
"4.6.14",
"4.6.2",
"4.6.3.1",
"4.6.4",
"4.6.5",
"4.6.6",
"4.6.7",
"4.6.8",
"4.6.9",
"4.7.0",
"4.7.1",
"4.7.2",
"4.7.3",
"4.8.0",
"4.8.0.1",
"4.8.1",
"4.8.1.1",
"4.8.1.2",
"4.8.2",
"4.8.3",
"4.8.4",
"4.9.0",
"4.9.1",
"4.9.2",
"4.9.3",
"4.9.4"
]
}