Weakness reference
CWE-654

Reliance on a Single Factor in a Security Decision

This weakness occurs when software makes a security decision based on only one piece of evidence—such as a single password, a single token, or a single…

01Summary

This weakness occurs when software makes a security decision based on only one piece of evidence—such as a single password, a single token, or a single characteristic of a request—rather than requiring multiple independent factors. Single-factor authentication or authorization is easier to bypass because compromising one factor grants full access. Multi-factor approaches significantly raise the bar for attackers by requiring them to compromise multiple, independent verification methods.

02How It Happens

Security decisions should ideally require multiple independent forms of verification. A single factor—whether a password, an API key, a session cookie, or an IP address—can be stolen, guessed, intercepted, or spoofed. When an application relies on only one factor to grant access to sensitive operations (password reset, account recovery, privilege escalation, or payment confirmation), an attacker who obtains or manipulates that single factor gains complete access. This is especially risky for high-value operations where the cost of compromise is high.

Common single-factor patterns include: accepting only a password for account recovery, trusting only a session cookie for authorization, relying solely on an API key without rate-limiting or IP validation, or using only a CAPTCHA to prevent automated abuse. Each of these can be defeated in isolation.

03Real-World Impact

Single-factor reliance has enabled account takeovers, unauthorized fund transfers, privilege escalation, and data exfiltration. An attacker who steals a user's password can immediately access their account. A leaked API key grants full API access without additional verification. A compromised session token allows impersonation. In regulated industries (finance, healthcare, government), single-factor authentication for sensitive operations often violates compliance requirements and can result in fines or loss of certification.

04Vulnerable & Fixed Patterns

Vulnerable pattern
def reset_password(user_email, new_password):
    # Only factor: email address (easily spoofed or intercepted)
    user = db.query("SELECT * FROM users WHERE email = ?", (user_email,))
    if user:
        db.execute("UPDATE users SET password = ? WHERE email = ?", 
                   (hash_password(new_password), user_email))
        return "Password reset successful"
    return "User not found"

Why it's vulnerable:
The function trusts only the email address to identify the user and authorize the password reset. An attacker who can intercept or spoof the email (or guess a valid email) can reset any user's password without proving they own the account.

Fixed pattern
def reset_password(user_email, reset_token, otp_code):
    # Multiple factors: valid reset token + time-limited OTP
    user = db.query("SELECT * FROM users WHERE email = ?", (user_email,))
    if not user:
        return "User not found"
    
    # Verify token is valid and not expired
    token_record = db.query(
        "SELECT * FROM reset_tokens WHERE user_id = ? AND token = ? AND expires_at > NOW()",
        (user.id, reset_token)
    )
    if not token_record:
        return "Invalid or expired token"
    
    # Verify OTP sent to user's registered phone or email
    if not verify_otp(user.id, otp_code):
        return "Invalid OTP"
    
    # All factors verified; proceed
    db.execute("UPDATE users SET password = ? WHERE id = ?", 
               (hash_password(new_password), user.id))
    db.execute("DELETE FROM reset_tokens WHERE user_id = ?", (user.id,))
    return "Password reset successful"
Vulnerable pattern
<?php
function authorize_payment($user_id, $amount) {
    // Only factor: session user_id (can be hijacked or forged)
    if (isset($_SESSION['user_id']) && $_SESSION['user_id'] == $user_id) {
        process_payment($user_id, $amount);
        return "Payment processed";
    }
    return "Unauthorized";
}
?>

Why it's vulnerable:
The function trusts only the session cookie to authorize a payment. If an attacker steals or hijacks the session, they can immediately process payments without any additional verification.

Fixed pattern
<?php
function authorize_payment($user_id, $amount, $otp_code, $password_confirmation) {
    // Multiple factors: session + password confirmation + OTP
    if (!isset($_SESSION['user_id']) || $_SESSION['user_id'] != $user_id) {
        return "Unauthorized";
    }
    
    // Factor 1: Verify password (user must re-authenticate for sensitive action)
    $user = get_user($user_id);
    if (!password_verify($password_confirmation, $user['password_hash'])) {
        return "Password confirmation failed";
    }
    
    // Factor 2: Verify OTP sent to registered phone
    if (!verify_otp_for_user($user_id, $otp_code)) {
        return "Invalid OTP";
    }
    
    // All factors verified; proceed
    process_payment($user_id, $amount);
    log_payment_authorization($user_id, $amount);
    return "Payment processed";
}
?>

05Prevention Checklist

Require multi-factor authentication (MFA) for sensitive operations:
password reset, account recovery, privilege escalation, financial transactions, and administrative actions. Combine at least two independent factors (something you know, something you have, something you are).
Use time-limited tokens for account recovery:
send a unique, cryptographically random token via email or SMS that expires after 15–30 minutes, and require the user to verify it before allowing a password reset.
Implement step-up authentication:
for high-risk operations, re-authenticate the user with a second factor even if they already have a valid session.
Avoid relying solely on IP address, user-agent, or device fingerprint:
these can be spoofed or hijacked. Use them as supplementary signals, not primary factors.
Rate-limit and monitor single-factor endpoints:
if you must use a single factor temporarily, add rate-limiting, CAPTCHA, and anomaly detection to reduce abuse.
Enforce MFA for administrative and privileged accounts:
admins should always use multi-factor authentication, regardless of internal network access.

06Signs You May Already Be Affected

Review your authentication and authorization logs for unusual patterns: multiple failed login attempts followed by success, password resets initiated from unfamiliar locations or times, or administrative actions performed outside normal business hours. Check whether sensitive operations (payments, account changes, privilege grants) require only a single verification step. If you find that password resets, API access, or high-value transactions require only one factor, you are at elevated risk.