Skip to content

Broken authentication

CWE-287OWASP A07:2021Updated August 29, 20265 min read

Broken authentication is an umbrella term for flaws in login and session handling that let an attacker impersonate another user. Think brute force without limits, insecure password storage, or predictable session tokens. The fix combines MFA, strong password hashing and solid session management.

The login screen is the front door of your application, and in practice that front door is often the weakest spot. Broken authentication, listed as Identification and Authentication Failures in the OWASP Top 10, covers every way attackers get around identity checks, from brute force to forged sessions. Here is how those attacks unfold and how to get login and session handling right.

What is broken authentication?

Broken authentication is the umbrella term for vulnerabilities in how an application establishes who is logging in and how it guards that logged-in state afterwards. It is not one specific bug but a family of them: weak password requirements, insecure password storage, login forms with no brake on the number of attempts, predictable session tokens, and sloppy password-reset flows. In every variant the outcome is the same: someone gains access to an account that is not theirs.

An everyday comparison: a hotel where the receptionist hands out a room key to anyone who mentions a room number, without ever asking for ID. Or a hotel that does check, but issues key cards with sequential numbers: whoever holds card 214 knows what 215 looks like. In both cases the lock is fine; it is the process around it that is broken.

It is worth realising that authentication is bigger than the login form alone. Password storage, session management, remember-me cookies, API keys and the password reset all belong to the same chain, and an attacker always goes for the weakest link.

How does an attack on authentication work?

Attackers rarely need to crack anything; they mostly use the front door as it was built. With credential stuffing they automatically replay email-and-password combinations leaked in earlier breaches. With brute force they let a script fire off thousands of passwords per minute. And if the application hands out weak tokens itself, they can skip the guessing entirely. The example below is a login endpoint that combines three classic mistakes.

Vulnerable:

// Plaintext password, chatty error messages, predictable token
app.post("/login", async (req, res) => {
  const user = await db.findUserByEmail(req.body.email);
  if (!user) {
    return res.status(401).send("Unknown email address");
  }
  if (user.password !== req.body.password) {
    return res.status(401).send("Incorrect password");
  }

  // "Session token": Base64 of the user id
  const token = Buffer.from("user:" + user.id).toString("base64");
  res.cookie("session", token);
  res.send("Logged in");
});

Several things go wrong at once here. The two different error messages reveal whether an email address exists (user enumeration), so an attacker first builds a list of valid accounts and then tests leaked passwords against exactly those. There is no limit on attempts, so that testing can run forever. The password also sits in plaintext in the database. One breach and every password is out in the open. The worst flaw, though, is the session token: Base64 is not encryption but an encoding anyone can reverse. An attacker simply encodes the text user:1, drops the result dXNlcjox into their cookie, and is logged in as user 1, often an administrator, without ever knowing a password.

The safe variant repairs all three weaknesses: passwords are compared as hashes, the error message gives nothing away, attempts are limited, and the session token comes from a cryptographically secure generator.

Safe:

// Hash comparison, generic error, rate limit, random token
app.post("/login", loginRateLimiter, async (req, res) => {
  const user = await db.findUserByEmail(req.body.email);
  const hash = user ? user.passwordHash : DUMMY_HASH;
  const valid = await bcrypt.compare(req.body.password, hash);

  if (!user || !valid) {
    return res.status(401).send("Invalid credentials");
  }

  // Session token: 32 random bytes, stored server-side
  const sessionId = crypto.randomBytes(32).toString("hex");
  await sessions.create(sessionId, user.id);
  res.cookie("session", sessionId, {
    httpOnly: true,
    secure: true,
    sameSite: "lax",
  });
  res.send("Logged in");
});

Note the detail with DUMMY_HASH: even when the account does not exist, the code still performs a hash comparison. That way every login attempt takes the same amount of time, and response timing reveals nothing about which email addresses exist. The session token is now 256 bits of randomness linked to a user only on the server; guessing or reversing it is hopeless. The cookie flags, finally, keep scripts and eavesdroppers away from the token.

The forgot-password feature is a second front door. A reset link that stays valid for a long time, works more than once, or contains a predictable token renders every other measure worthless. Treat reset tokens as strictly as passwords: random, short-lived and single-use.

What is the impact of broken authentication?

The immediate damage is account takeover. An attacker logged in as a customer sees personal data, order history and stored payment methods, and can act in the victim’s name. If it is an administrator account, the impact shifts from one account to the entire application: every user’s data, every setting, and often a stepping stone into the underlying infrastructure.

At scale it becomes a business risk. Credential stuffing is cheap to automate, so a single weak login form can yield thousands of hijacked accounts within days, followed by fraud, chargebacks and a reportable data breach under privacy law. Reputational damage comes on top: users rarely forgive a hacked account.

What makes these attacks especially treacherous is how little they stand out. A hijacked session or a successful credential-stuffing login looks in the logs like an ordinary user signing in. Because the consequences range from one compromised account to full compromise of the application, the severity runs from high to critical.

How do you detect broken authentication?

Testers start with what the application gives away: differences in error messages or response times that betray which accounts exist. Next comes the brake on attempts: does the form accept hundreds of passwords in a row without lockout or delay? Session tokens are examined too, by collecting dozens of them and analysing their patterns, length and predictability. Finally the life cycle: does a session stay valid after logout or a password change, and how strict is the reset flow?

Automated scanners catch the surface-level signals at best; the logic behind them takes manual work. This is exactly the kind of ground AssistSec covers systematically during a penetration test, from token analysis to reset flow, so you know precisely which route actually leads an attacker into an account.

How do you prevent broken authentication?

  • Enable multi-factor authentication (MFA), at minimum for administrators. A leaked or guessed password is then no longer enough.
  • Store passwords as hashes with bcrypt, scrypt or Argon2, never in plaintext and never with fast hashes such as MD5 or SHA-1.
  • Limit login attempts with rate limiting, increasing delays or a temporary lockout, per account and per IP address.
  • Keep error messages generic, regardless of whether the email address exists, and keep response times constant too.
  • Generate session tokens with a cryptographically secure generator, store them server-side and give cookies the httpOnly, secure and sameSite flags.
  • Rotate the session token right after login and invalidate all sessions on logout and after a password change.
  • Make reset tokens single-use and short-lived, and confirm sensitive changes through a second channel.
  • Check new passwords against lists of leaked passwords instead of relying on complexity rules alone.
  • Have the whole authentication chain tested regularly, including session management and reset flows. That is where the flaws scanners miss live.

Sources

Frequently asked questions

What counts as broken authentication?

Any flaw that lets an attacker pass as someone else: weak or leaked passwords, brute force without limits, insecure password storage, predictable session tokens, and vulnerable password-reset flows.

What is credential stuffing?

An attack that automatically tries email-and-password combinations leaked in earlier breaches against other sites. Because so many people reuse passwords, a small but profitable percentage always succeeds.

Is a strict password policy enough?

No. Complexity rules do little against reused or leaked passwords and nothing against weak session management. Combine a sound policy with MFA, rate limiting and secure session tokens.

Does MFA help against broken authentication?

It is the single most effective measure: a stolen or guessed password is no longer enough to log in. MFA does not protect against session-management flaws though, so that foundation still has to be solid.

Related articles

Press / to search · Esc