Weakness reference
CWE-522

Insufficiently Protected Credentials

This weakness occurs when authentication credentials—usernames, passwords, API keys, tokens, or other secrets—are transmitted or stored without adequate…

01Summary

This weakness occurs when authentication credentials—usernames, passwords, API keys, tokens, or other secrets—are transmitted or stored without adequate protection. Attackers who gain access to unencrypted or weakly encrypted credentials can impersonate legitimate users or systems. This is a foundational security failure that can lead to account takeover, data breaches, and lateral movement within a network.

02How It Happens

Credentials become vulnerable when developers store them in plaintext in databases, configuration files, or logs, or transmit them over unencrypted channels. Common patterns include hardcoding secrets in source code, storing passwords without hashing, using deprecated or custom encryption schemes, or relying on HTTP instead of HTTPS. Even when encryption is used, weak key management—such as storing encryption keys alongside encrypted data or using a single key across all users—undermines the protection. The root cause is often a misunderstanding of the difference between encryption (which protects confidentiality in transit) and hashing (which protects stored passwords), or a failure to apply either consistently.

03Real-World Impact

If credentials are exposed, attackers can log in as legitimate users without triggering alerts or requiring password resets. This enables account takeover, unauthorized access to sensitive data, and privilege escalation. In multi-user systems, a single compromised admin credential can grant access to all user accounts and system resources. Exposed API keys allow attackers to impersonate applications and access third-party services. The damage compounds if the same password is reused across multiple platforms, turning a single breach into a cascade of compromises.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import sqlite3

conn = sqlite3.connect('app.db')
cursor = conn.cursor()

username = 'alice'
password = 'MySecretPassword123'  # plaintext password

# Store credentials directly without hashing
cursor.execute(
    "INSERT INTO users (username, password) VALUES (?, ?)",
    (username, password)
)
conn.commit()

Why it's vulnerable:
The password is stored in plaintext in the database. Anyone with database access can read it directly, and if the database is breached, all passwords are immediately compromised.

Fixed pattern
import sqlite3
import hashlib
import secrets

conn = sqlite3.connect('app.db')
cursor = conn.cursor()

username = 'alice'
password = 'MySecretPassword123'

# Hash the password with a salt before storing
salt = secrets.token_hex(16)
hashed = hashlib.pbkdf2_hmac('sha256', password.encode(), salt.encode(), 100000)

cursor.execute(
    "INSERT INTO users (username, password_hash, salt) VALUES (?, ?, ?)",
    (username, hashed.hex(), salt)
)
conn.commit()
Vulnerable pattern
<?php
$username = 'alice';
$password = $_POST['password'];

// Store password in plaintext
$mysqli = new mysqli('localhost', 'root', 'db_password', 'app_db');
$mysqli->query(
    "INSERT INTO users (username, password) VALUES ('$username', '$password')"
);
?>

Why it's vulnerable:
The password is stored without hashing, and the query uses string concatenation (which also introduces SQL injection risk). Any database compromise exposes all user passwords in readable form.

Fixed pattern
<?php
$username = 'alice';
$password = $_POST['password'];

// Hash the password using a modern algorithm
$password_hash = password_hash($password, PASSWORD_BCRYPT);

$mysqli = new mysqli('localhost', 'root', 'db_password', 'app_db');
$stmt = $mysqli->prepare("INSERT INTO users (username, password_hash) VALUES (?, ?)");
$stmt->bind_param('ss', $username, $password_hash);
$stmt->execute();
?>

05Prevention Checklist

Hash passwords with a strong algorithm
(bcrypt, scrypt, or Argon2) and a unique salt per user; never store plaintext passwords.
Use HTTPS for all credential transmission
to prevent interception over the network; disable HTTP entirely for authenticated endpoints.
Never hardcode secrets
in source code, configuration files, or version control; use environment variables or a secrets management system.
Encrypt sensitive data at rest
using a strong cipher (AES-256) with keys stored separately from the encrypted data.
Rotate credentials regularly
and invalidate old tokens/API keys; implement expiration for session tokens and temporary credentials.
Audit logs and backups
to ensure credentials are not accidentally logged or stored in plaintext backups; mask sensitive fields in logs.

06Signs You May Already Be Affected

Check your database and configuration files for plaintext passwords, API keys, or tokens. Review application logs to see if credentials are being written to disk. If you find hardcoded secrets in source code repositories or unencrypted backups, assume they may have been exposed. Look for unexpected login activity from unfamiliar IP addresses or unusual API usage patterns, which may indicate compromised credentials are in use.

07Related Recent Vulnerabilities