# Step-up uses equal or higher strength than initial login

- **Pattern:** `ab-001466` (`finserv-session-security.step-up-auth.step-up-strength-equivalent`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001466
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001466)

## Why it matters

Step-up authentication is only meaningful if the challenge it presents is at least as hard to satisfy as the initial login. Downgrading from a password+biometric login to a plain OTP step-up means the attacker who cannot replicate the biometric at login can instead wait for the step-up prompt and satisfy it with a weaker factor. CWE-287 (Improper Authentication) and NIST 800-63B AAL2 both require that step-up methods match or exceed the assurance level of the authenticating session. OWASP A07 identifies authentication downgrade as a category-defining failure. In practice, a strength mismatch turns step-up into a false signal — it appears to add security while actually lowering the bar.

## Severity rationale

Medium because strength downgrade does not eliminate the step-up challenge but renders it easier to satisfy than the original login, reducing the additional security margin that step-up is supposed to provide.

## Remediation

Define strength levels explicitly in `src/lib/authStrength.ts` and enforce that the step-up method meets or exceeds the login method's level:

```js
const STRENGTH: Record<string, number> = {
  'password': 1,
  'otp': 1,
  'password+otp': 2,
  'biometric': 2,
  'password+biometric': 3
};

export async function requireStepUpAuth(
  session: Session,
  minOverride?: number
): Promise<boolean> {
  const loginStrength = STRENGTH[session.authMethod] ?? 1;
  const requiredStrength = Math.max(loginStrength, minOverride ?? 0);
  const stepUpMethod = await promptStepUp(requiredStrength);
  return STRENGTH[stepUpMethod] >= requiredStrength;
}
```

Never hard-code step-up to a fixed method without first querying the session's login strength — users who authenticated at level 3 must be challenged at level 3.

## Detection

- **ID:** `step-up-strength-equivalent`
- **Severity:** `medium`
- **What to look for:** Enumerate all authentication methods available for login and step-up. Assign a strength level to each (e.g., password=1, OTP=1, password+OTP=2, biometric=2, password+biometric=3). Compare login strength vs. step-up strength. Quote the actual authentication methods found. A step-up method weaker than the initial login must not pass.
- **Pass criteria:** Step-up authentication strength level is at least 1 (on a scale of 1-3) and equal to or greater than the initial login authentication strength level. Count all auth methods — report the ratio even on pass (e.g., "Login strength: level 2 (password+OTP), step-up strength: level 2 (biometric) — meets minimum").
- **Fail criteria:** Step-up uses a weaker authentication method than login (step-up strength level < login strength level).
- **Skip (N/A) when:** No step-up authentication is configured (caught by step-up-sensitive-ops check) — cite the missing configuration found.
- **Detail on fail:** `"Login requires strength level 3 (password+biometric). Step-up is level 1 (OTP only) — below minimum."`
- **Remediation:** Define step-up strength requirements that match or exceed login strength (in `src/lib/authStrength.ts`):
  ```js
  // lib/authStrength.ts
  const authStrengthLevels = {
    'password': 1,
    'otp': 1,
    'password+otp': 2,
    'biometric': 2,
    'password+biometric': 3
  };

  export async function requireStepUpAuth(session: Session, minStrength: number) {
    // Determine initial login strength
    const loginStrength = authStrengthLevels[session.authMethod];
    // Require step-up of equal or higher strength
    const requiredStepUpStrength = loginStrength;
    const stepUpMethod = await promptStepUp(requiredStepUpStrength);
    return authStrengthLevels[stepUpMethod] >= requiredStepUpStrength;
  }
  ```

## External references

- cwe CWE-287
- owasp A07
- nist SP-800-63B §4.2

Taxons: access-control

HTML version: https://auditbuffet.com/patterns/ab-001466
