CWE-521 in APIs
- CWE ID
- CWE-521
- Category
- Authentication
- Severity
- MEDIUM
- Short Name
- Weak Passwords
What is CWE-521?
CWE-521 refers to the weakness Weak Password Requirements. This occurs when an application allows users to choose passwords that are easily guessable or susceptible to brute-force attacks due to insufficient complexity requirements. The weakness manifests when authentication systems accept passwords that are too short, lack character variety, or use common patterns that attackers can quickly enumerate.
CWE-521 in API Contexts
In API authentication systems, CWE-521 appears when endpoints accept weak credentials during registration, password reset, or authentication flows. APIs often handle authentication at scale, making weak password requirements particularly dangerous since automated attacks can exploit them across many users simultaneously.
Common manifestations in APIs include:
- Registration endpoints accepting passwords under 8 characters
- No enforcement of character variety (uppercase, lowercase, numbers, symbols)
- Acceptance of common passwords from breach databases
- Lack of checks against password similarity (e.g., 'password123')
- No rate limiting on authentication attempts
Consider this vulnerable API endpoint:
POST /api/v1/auth/register
{
"username": "user1",
"password": "123456"
}
// Server accepts without validation
// Returns: 201 CreatedThis allows attackers to create accounts with trivially guessable passwords, then potentially escalate privileges or access other users' data if the system has broader vulnerabilities.
Detection
Detecting CWE-521 requires examining both the API specification and runtime behavior. middleBrick's API security scanner automatically tests password requirements by attempting to register accounts with progressively weaker passwords and analyzing the responses.
middleBrick scans for this weakness by:
- Testing minimum password length enforcement
- Checking character variety requirements
- Attempting common weak passwords from breach databases
- Analyzing authentication error messages for information disclosure
- Verifying rate limiting on authentication endpoints
The scanner reports findings with severity levels and provides specific recommendations for each detected weakness. For example, if an API accepts 'password' as a valid credential, middleBrick flags this as a critical finding with immediate remediation guidance.
Manual detection methods include:
curl -X POST https://api.example.com/register \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"123"}'
# If this succeeds, weak password requirements exist
# Test progressively weaker passwords to find the actual minimumRemediation
Fixing CWE-521 requires implementing strong password policies at the API level. Here are effective remediation strategies with code examples:
1. Minimum Length and Character Requirements
// Node.js/Express validation middleware
const passwordValidator = (req, res, next) => {
const { password } = req.body;
if (!password) {
return res.status(400).json({
error: 'Password is required'
});
}
if (password.length < 12) {
return res.status(400).json({
error: 'Password must be at least 12 characters long'
});
}
const hasUppercase = /[A-Z]/.test(password);
const hasLowercase = /[a-z]/.test(password);
const hasNumber = /[0-9]/.test(password);
const hasSymbol = /[^A-Za-z0-9]/.test(password);
if (!hasUppercase || !hasLowercase || !hasNumber || !hasSymbol) {
return res.status(400).json({
error: 'Password must include uppercase, lowercase, number, and symbol'
});
}
next();
};
2. Common Password Prevention
// Using a common passwords list (simplified example)
const commonPasswords = require('./common-passwords.json'); // 100k+ entries
const checkCommonPassword = (password) => {
const normalized = password.toLowerCase().trim();
return commonPasswords.includes(normalized);
};
// In your validation middleware
if (checkCommonPassword(password)) {
return res.status(400).json({
error: 'Password is too common and easily guessable'
});
}
3. Rate Limiting Authentication
const rateLimit = require('express-rate-limit');
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 requests per windowMs
message: 'Too many authentication attempts, please try again later',
skipSuccessfulRequests: true
});
// Apply to authentication routes
app.post('/api/v1/auth/login', authLimiter, loginHandler);
app.post('/api/v1/auth/register', authLimiter, registerHandler);
4. Password Strength Feedback
// Return specific feedback for password requirements
const validatePassword = (password) => {
const errors = [];
if (password.length < 12) {
errors.push('At least 12 characters long');
}
if (!/[A-Z]/.test(password)) {
errors.push('At least one uppercase letter');
}
if (!/[a-z]/.test(password)) {
errors.push('At least one lowercase letter');
}
if (!/[0-9]/.test(password)) {
errors.push('At least one number');
}
if (!/[^A-Za-z0-9]/.test(password)) {
errors.push('At least one symbol');
}
if (checkCommonPassword(password)) {
errors.push('Not a common or compromised password');
}
return errors;
};
// Client-side can call this first for immediate feedback
// Server still validates on submission