WordPress / WordPress/two-factor

Keep authentication fail-closed when provider filters change between lookups

Open
#943 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
825
Forks
187
Avg merge
2d 11h
Merged PRs (30d)
17

Description

Security problem

Authentication can fail open when two_factor_providers returns different provider sets across the multiple lookups performed during one request. A user with persisted enabled 2FA can be treated as not using 2FA, leaving auth cookies enabled and REST/XML-RPC password authentication unrestricted.

Minimized call schedule

For one enabled provider, make successive provider-filter snapshots follow:

[present, absent, present]

Observed flow around class-two-factor-core.php:702-735, :822-875, and :936-953:

  1. Initial supported-provider lookup includes the provider.
  2. Availability lookup excludes it and returns an empty array rather than a durable error state.
  3. Enabled-provider lookup includes it again.
  4. is_user_using_two_factor() returns false.
  5. filter_authenticate() does not enforce the second factor.

Evidence

Found during an isolated aggressive multisite fuzz campaign against #933:

  • 50,001 randomized provider states across three deterministic seeds
  • 5,000 transition sequences / 15,000 cross-site steps
  • Reproduced on PHP 7.4 + WordPress 6.9 and PHP 8.3 + WordPress trunk
  • Seeds observed 998/51 and 959/48 claimed-state/cookie fail-open events
  • No production traffic or state used

Expected

Provider resolution used for one authentication decision must derive from one consistent snapshot or otherwise preserve a durable fail-closed state. Dynamic provider deregistration/re-registration during the request must never downgrade an account with persisted 2FA claims to password-only authentication.

Related: #933 fixes a fatal under a different provider-removal schedule, but this authentication issue appears to predate its latest commit.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in class-two-factor-core.php at lines 702-735, 822-875, and 936-953, and trace the three provider-filter lookups using the [present, absent, present] schedule. Confirm that one authentication decision preserves a fail-closed state when providers change, including the filter_authenticate() path, and verify the behavior against the related provider-removal case in #933.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
authentication, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.