Skip to content

[ticket/17680] Add escalating cooldown for failed login attempts#6985

Open
ECYaz wants to merge 1 commit into
phpbb:masterfrom
ECYaz:ticket/17680
Open

[ticket/17680] Add escalating cooldown for failed login attempts#6985
ECYaz wants to merge 1 commit into
phpbb:masterfrom
ECYaz:ticket/17680

Conversation

@ECYaz

@ECYaz ECYaz commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Checklist:

  • Correct branch: master for new features; 3.3.x for fixes
  • Tests pass
  • Code follows coding guidelines: master and 3.3.x
  • Commit follows commit message format

Once the maximum number of login attempts for a username or IP address is
exceeded, further login attempts are rejected for a cooldown period after each
failed attempt. The cooldown is enforced independently of the CAPTCHA, so it
also slows brute force attacks on boards whose CAPTCHA has been broken —
currently a broken CAPTCHA means there is effectively no mitigation at all.

How it works

  • Two new settings under ACP > Server configuration > Security:
    login_cooldown_min (default 1 minute, 0 disables the cooldown) and
    login_cooldown_max (default 10 minutes). The cooldown starts at the
    minimum, grows by the same amount for every further failed attempt beyond
    the threshold, and is capped at the maximum.
  • The check runs in the db auth provider at the point where the CAPTCHA
    decision is made, before the current attempt is recorded — so attempts
    rejected by the cooldown do not extend it.
  • Keying: exceeding the per-IP threshold enforces the cooldown for that
    IP; exceeding the per-user threshold enforces it for the username + IP
    combination only. A third party's failed attempts therefore cannot lock the
    account owner out (a cooldown keyed to the account alone would allow keeping
    any account permanently locked with one failed attempt per window).
  • No schema change. The timestamps come from the existing login attempts
    table, which already records IP, username and time for every attempt. The
    session GC now retains those rows for at least login_cooldown_max, so an
    active cooldown cannot lose its reference timestamp.
  • New LOGIN_ERROR_COOLDOWN status with a "You need to wait X minutes and
    Y seconds before trying to log in again." message. All three places that
    render login errors handle it (login_box, OAuth account linking, feed HTTP
    auth) via a shared formatter. During the cooldown no CAPTCHA is displayed;
    once it expires the CAPTCHA gate applies as before.
  • The response for a nonexistent username on the IP path is identical to the
    one for existing usernames, so the cooldown adds no new username-probing
    signal.

The countdown timer with meta refresh suggested in the ticket can be a
follow-up; the server enforces the cooldown either way.

Tests

  • tests/auth/ticket17680_login_cooldown_test.php: threshold trip, correct
    password rejected during cooldown, rejected attempts not extending the
    cooldown, username + IP keying, escalation, expiry, disabling via 0, and
    message formatting.
  • tests/functional/ticket17680_login_cooldown_test.php: the login form
    shows the cooldown message after the threshold is exceeded, for the wrong
    and the correct password.

Tracker ticket:

https://tracker.phpbb.com/browse/PHPBB-17680

Once the maximum number of login attempts for a username or IP address
is exceeded, reject further attempts for a configurable cooldown period
after each failed attempt, independently of the CAPTCHA. The cooldown
starts at login_cooldown_min seconds, grows by the same amount for every
further failed attempt and is capped at login_cooldown_max seconds.

The cooldown is keyed to the source of the failed attempts: exceeding
the per-IP threshold enforces it for the IP, while exceeding the
per-user threshold enforces it for the username and IP combination
only, so failed attempts by a third party cannot lock the account owner
out. The timestamps come from the existing login attempts table, whose
cleanup now also honours the maximum cooldown time.

PHPBB-17680
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant