This weakness occurs when an application trusts data it shouldn't—typically information stored on the client side or in places an attacker can modify—to verify…
This weakness occurs when an application trusts data it shouldn't—typically information stored on the client side or in places an attacker can modify—to verify a user's identity. If the application assumes this data cannot be changed, an attacker can forge or alter it to bypass authentication entirely. This is a critical flaw because authentication is the first line of defense against unauthorized access.
02How It Happens
Authentication systems work by verifying that a user is who they claim to be. The vulnerability arises when developers assume certain data—such as cookies, hidden form fields, URL parameters, or local storage values—are tamper-proof and use them as the sole basis for granting access. In reality, an attacker can intercept, modify, or fabricate this data before sending it to the server. If the server never validates the data against a trusted source (like a session database or cryptographic signature), the attacker can simply change a user ID, role flag, or token to impersonate someone else or escalate privileges.
The root cause is a misunderstanding of the trust boundary: anything that originates from or passes through the client is inherently untrusted, even if it appears to be "locked down" or "read-only" in the user interface.
03Real-World Impact
Successful exploitation allows an attacker to log in as any user without knowing their password, access accounts with elevated privileges, or bypass multi-factor authentication checks. This can lead to unauthorized data access, account takeover, fraud, and compliance violations. In high-stakes applications (banking, healthcare, government), this type of flaw can expose sensitive personal information or enable financial theft.
Why it's vulnerable: The is_admin flag comes directly from the client (a form field or cookie) and is trusted without verification. An attacker can modify the request to set is_admin=true and gain admin access.
Fixed pattern
from flask import Flask, request, session
import secrets
app = Flask(__name__)
app.secret_key = secrets.token_hex(32)
# Simulated user database
USERS = {
'alice': {'password_hash': 'hashed_pwd_1', 'is_admin': True},
'bob': {'password_hash': 'hashed_pwd_2', 'is_admin': False}
}
@app.route('/login', methods=['POST'])
def login():
username = request.form.get('username')
password = request.form.get('password')
# Verify credentials against server-side database
if username in USERS and verify_password(password, USERS[username]['password_hash']):
session['user_id'] = username
# Store only the username; fetch role from database on each request
return "Logged in"
return "Invalid credentials"
@app.route('/admin')
def admin_panel():
username = session.get('user_id')
# Always check the server-side database, never trust client data
if username and USERS.get(username, {}).get('is_admin'):
return "Admin panel"
return "Access denied"
Why it's vulnerable: The role field is set directly from user input and trusted without server-side verification. An attacker can modify the POST data to set role=admin.
Fixed pattern
<?php
session_start();
$users = [
'alice' => ['password_hash' => 'hashed_pwd_1', 'role' => 'admin'],
'bob' => ['password_hash' => 'hashed_pwd_2', 'role' => 'user']
];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
// Verify credentials against server-side database
if (isset($users[$username]) && password_verify($password, $users[$username]['password_hash'])) {
$_SESSION['user_id'] = $username;
// Do NOT store role in session; fetch it from database on each request
}
}
// Always check the server-side database
$username = $_SESSION['user_id'] ?? null;
if ($username && isset($users[$username]) && $users[$username]['role'] === 'admin') {
echo "Admin panel";
} else {
echo "Access denied";
}
?>
05Prevention Checklist
Never trust client-supplied authentication data. Do not use form fields, cookies, or URL parameters as the sole basis for identity or role decisions.
Store sensitive state server-side only. Keep user roles, permissions, and authentication status in a server-side session store or database, not in cookies or hidden fields.
Validate every request against the database. On each protected action, re-verify the user's identity and permissions by querying the authoritative server-side source.
Use cryptographically signed tokens if needed. If you must pass data to the client, sign it with a server-side secret (e.g., JWT with HMAC) so tampering is detectable.
Implement proper session management. Use framework-provided session handling (Flask sessions, PHP $_SESSION) with secure, server-side storage.
Test authentication logic with modified requests. Use a proxy tool to intercept and alter authentication-related fields and verify the server rejects them.
06Signs You May Already Be Affected
Look for authentication checks that read directly from cookies, hidden form fields, or URL parameters without querying a database or session store. If you can modify a request (using browser developer tools or a proxy) to change a user ID, role, or permission flag and gain unauthorized access, your application is vulnerable. Check server logs for unusual privilege escalations or access patterns that don't match normal user behavior.