☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
[ VENDOR STATS ]
CVSS: 8.1 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H 🐛 CWE-324
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2026-39923

CVE-2026-39923 Vulnerability in Flarum
📅 PUBLISHED: 2026-08-05 00:00 UTC 🔄 UPDATED: 2026-09-23 20:16 UTC
[ OFFICIAL PATCH DEPLOYED ↓ ] FIX: LIKELY — 2 independent sources confirm fix
[ DEFENSE PATCH ↓ ]
💣 PoC: None
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.26%
👁️
0.26% probability
6.5× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
🥷 MITRE: T1110
👁️
MITRE ATT&CK Tactic - Describes the strategy hackers use to execute this attack.
Patch available — upgrade to latest release
CVSS VECTOR BREAKDOWN 8.1
AV: N Attack Vector Network
AC: H Attack Complexity High
PR: N Privileges Required None
UI: N User Interaction None
S: U Scope Unchanged
C: H Confidentiality High
I: H Integrity High
A: H Availability High
8.1
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2026-39923 is a high-severity password reset token expiry bypass vulnerability in Flarum, an open-source PHP forum platform. Affecting versions prior to 1.8.16, this flaw allows an unauthenticated attacker to reuse expired password reset tokens by submitting them directly to the password reset processing endpoint, bypassing the 24-hour token lifetime validation that is enforced only during form rendering. Successful exploitation enables an attacker to reset the password of any account — including administrator accounts — and obtain a fully authenticated session, leading to complete account takeover and potential site compromise. Given the CVSS score of 8.1 and the authentication-bypass nature of the flaw, this vulnerability represents a critical risk for all Flarum deployments not running the patched version.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Technical Analysis

The vulnerability resides in Flarum's password reset workflow, specifically in the SavePasswordController::handle() method. The password reset mechanism is implemented as a two-phase process:

  1. Request Phase: A user requests a password reset for an account. The application generates a unique, cryptographically random token and stores it in the password_tokens database table, along with the associated user ID and a creation timestamp (created_at). An email is then sent to the account owner containing a link to the reset form, which includes the token as a query parameter.

  2. Reset Phase: The user clicks the email link, which renders a form via the PasswordResetController (or similar form-rendering controller). The form includes the token (typically as a hidden field). Upon submission, the SavePasswordController receives the token and password, validates the token, and updates the account password.

The critical flaw is an asymmetric validation of token expiry between the two phases. During form rendering, the application correctly validates the token's age by checking the created_at timestamp against the 24-hour expiry window. If the token exceeds 24 hours, the form render returns an error. However, in SavePasswordController::handle(), the only token validation performed is via the PasswordToken::findOrFail() call. This method retrieves the token record from the database based on the token's hash but performs no expiration timestamp validation whatsoever.

An attacker who obtains a valid password reset token (for example, by triggering a password reset for a target account and intercepting the email, or through other means such as a mailbox compromise) can therefore present that token to the reset processing endpoint at any point in the future — days, weeks, or months later — and successfully change the target account's password. The 24-hour expiry check is effectively cosmetic; it only protects the form-rendering path but not the actual password update operation.

The vulnerable code path can be summarized as:

// Vulnerable — no expiry check
class SavePasswordController {
    public function handle() {
        $token = PasswordToken::findOrFail($this->request->get('token'));
        // Token found — but expiry NEVER checked
        $user = $token->user;
        $user->changePassword($this->request->get('password'));
        // Password changed successfully
    }
}

Attack surface: The vulnerability is exploitable by any unauthenticated network attacker who possesses a valid password reset token for a target account. The token's lifetime is not a mitigating factor. The attack requires only an HTTP POST request to the password reset endpoint (/reset/confirm or similar) with token and password parameters. The high Attack Complexity (AC:H) in the CVSS vector reflects the requirement to obtain a valid token, but once obtained, exploitation is trivial.

Exploitation Scenarios

Attackers can chain this vulnerability into a complete account takeover attack chain. The following is a realistic exploitation scenario:

Step 1 — Reconnaissance and Target Identification

The attacker identifies a Flarum forum (version ≤ 1.8.15) as a target. Fingerprinting can be performed by examining response headers (X-Powered-By, cookies such as flarum_session), or by fetching nflarum.github.io/flarum-framework and looking for version disclosure in the meta[name="generator"] tag. The attacker then selects a high-value target account such as an administrator with elevated privileges.

Step 2 — Token Acquisition

The attacker triggers a password reset for the target account by submitting a POST request to the password reset initiation endpoint (e.g., POST /reset) with the target's email address. This action is unauthenticated and rate-limit is typically not enforced on this endpoint. The reset email is delivered to the target's mailbox. The attacker must then obtain that email. Common acquisition vectors include:

  • Mailbox compromise: The target uses a weak or reused password themselves.
  • Mail relay misconfiguration: The forum's mail settings misdirect password reset emails to an attacker-controlled address (e.g., if the target's email is overridden in the database).
  • Insider threat / shared mailbox: In smaller organizations, the forum admin's mailbox may be accessible to a disgruntled employee.
  • Token leakage: The attacker may already possess a token from a prior reset request (this is the core of the 24-hour bypass).

Step 3 — Weaponization of the Expired Token

Once the attacker has the token (either directly from the email link or extracted from a prior interception), they wait beyond the 24-hour expiry window. Any period exceeding 24 hours works — there is no upper bound.

Step 4 — Password Reset Execution

After the expiry period, the attacker crafts a direct HTTP request to the reset processing endpoint:

POST /reset/confirm HTTP/1.1
Host: forum.example.com
Content-Type: application/x-www-form-urlencoded

token=[EXPIRED_TOKEN]&password=AttackerP@ssw0rd!2026&password_confirmation=AttackerP@ssw0rd!2026

Because SavePasswordController::handle() calls PasswordToken::findOrFail() without expiry validation, the token is accepted. Alternatively, the attacker can submit the token to the form-rendering URL first to obtain a valid session CSRF token, then submit the form to the processing endpoint.

Step 5 — Post-Exploitation Impact

  • The attacker is now authenticated as the target user. If the target is an administrator, the attacker gains full control of the forum.
  • The attacker can now upload malicious extensions (PHP files) to achieve remote code execution on the underlying server, modify all posts, exfiltrate user PII (emails, IP addresses, private messages), and pivot to the hosting infrastructure.
  • The attacker can also change the forum's mail settings to intercept future password reset requests for other users, enabling a "password reset worm" that cascades across all accounts, including other administrators.

Impact Assessment

Confidentiality (High): Successful exploitation grants an authenticated session. For administrator accounts, an attacker gains complete access to all private user data, private discussions, IP addresses, email addresses, and moderation logs. The attacker can read any private data visible within the forum.

Integrity (High): The attacker can modify forum content — editing, deleting, or injecting posts. As an administrator, they can alter user profiles, change forum configuration, install malicious extensions, and modify the underlying server files if PHP upload is enabled.

Availability (High): An attacker with administrator access can deface the forum, lock out legitimate users, disable the site, or destroy the database.

Attack Complexity (High): The attacker must obtain a valid password reset token, which requires either mailbox access or interception of a reset email. This elevates the complexity but does not prevent exploitation — once a token is obtained, the 24-hour window poses no barrier.

Scope / Blast Radius: All Flarum deployments running versions prior to 1.8.16 with password reset functionality enabled (default configuration). The vulnerability is classifiable under CWE-324 (Use of a Cryptographic Primitive with a Risky Implementation) — the token is cryptographically sound but the validation logic around its expiry is flawed.

Exploitability in the Wild: No public PoC or active exploitation has been reported as of this writing. The EPSS score has not yet been assigned by FIRST.org. The vulnerability is not listed on CISA's Known Exploited Vulnerabilities (KEV) catalog. However, the flaw is trivial to exploit once a token is obtained, and it is reasonable to expect weaponization shortly after public disclosure.

Detection Guidance

Sigma Rule

title: Flarum Password Reset Token Expiry Bypass Exploitation
id: c8f3a2d1-7e5b-4a1c-9f2d-3b6e8a0c4f1e
status: experimental
description: Detects attempts to submit expired password reset tokens to the Flarum reset processing endpoint
author: Valters IT Security Team
date: 2026-02-10
logsource:
  category: web
  product: nginx
  service: http
detection:
  selection_uri:
    cs-method: POST
    cs-uri-extension: contains: reset
  selection_response:
    http.response.status_code: 200
  selection_body:
    http.request.body: contains: password
  condition: selection_uri and selection_response and selection_body
falsepositives:
  - Legitimate password reset submissions within the valid 24-hour window
level: high
tags:
  - attack.reconnaissance
  - attack.credential-access
  - cve.2026.39923

YARA Rule

rule Flarum_Password_Token_Expiry_Bypass_CVE_2026_39923
{
    meta:
        author = "Valters IT Security"
        date = "2026-02-10"
        description = "Detects Flarum source code lacking expiry validation in SavePasswordController"
        cve = "CVE-2026-39923"
        severity = "high"
    strings:
        $a = "class SavePasswordController" ascii nocase
        $b = "PasswordToken::findOrFail" ascii nocase
        $c = "created_at" ascii nocase
        $d = "changePassword" ascii nocase
        $missing_expiry = "expires_at" ascii nocase
    condition:
        all of them and not $missing_expiry
}

Suricata IDS Rule

alert http any any -> any any (msg:"ET EXPLOIT Flarum Password Reset Token Expiry Bypass Attempt (CVE-2026-39923)"; flow:established,to_server; http.method; content:"POST"; http.uri; content:"reset"; http.request_body; content:"token="; http.request_body; content:"password="; http.request_body; pcre:"/password_confirmation=/i"; http.host; content:"!"; metadata: former_category EXPLOIT; classtype: attempted-admin; sid: 202639923001; rev: 1; reference: cve, CVE-2026-39923;)

Elastic Detection

sequence by source.ip
  with maxspan=10m
  [ http where event.category == "web" and http.request.method == "POST"
    and url.path contains "reset" and request.body contains "token="
    and request.body contains "password=" ]

Additional rule for the server-side anomaly:

process where event.action == "executed" and
  process.parent.name == "php-fpm" and
  process.args : "*SavePasswordController*"

Splunk SPL Query

index=web sourcetype=access_combined
| where method="POST" AND uri_path LIKE "%reset%"
| search body="*token=*" body="*password=*"
| rex field=uri_path "(?<endpoint>/[^?]+)"
| eval suspicious = if(endpoint=="reset/confirm" OR endpoint=="password/reset", 1, 0)
| where suspicious=1
| stats count as attempts by src_ip, uri_path, _time
| where attempts > 1
| sort -_time

Wazuh OSSEC Rule

<group name="flarum,web_attacks,">
  <rule id="100230" level="10">
    <if_sid>30008</if_sid>
    <match>POST</match>
    <match>reset</match>
    <match>token=</match>
    <match>password=</match>
    <description>Flarum password reset token expiry bypass attempt (CVE-2026-39923)</description>
    <group>cve-2026-39923,</group>
    <mitre>
      <id>T1110</id>
    </mitre>
  </rule>
</group>

Mitigation & Patch Guidance

Patch Confidence: 2/4 (CLAIMED) — A single source (NVD) claims a patched version exists (1.8.16), but this has not been independently confirmed by the Flarum project team on their official advisory channels at the time of writing.

1. Immediate Mitigations (if upgrade is not immediately possible):

  • Disable automatic password reset functionality: Edit the Flarum configuration to redirect the /reset route to a 404 page, or use a Web Application Firewall (WAF) rule to block POST requests to /reset/confirm and /reset endpoints. This eliminates the attack vector entirely.
  • Rate-limit the password reset endpoint: Configure nginx or the WAF to rate-limit POST requests to /reset* (e.g., max 5 requests per IP per hour). This limits an attacker's ability to brute-force or abuse the endpoint.
  • Restrict access to the admin control panel: Limit administrative login to trusted IP ranges or enforce MFA on all administrator accounts. While this doesn't fix the vulnerability, it reduces the blast radius if an admin account is compromised.
  • Monitor password reset emails: Review the forum's mail logs for any password reset requests sent to unknown or external domains. If a reset email goes to an unexpected recipient, investigate immediately.

2. Patch / Upgrade Steps:

  • Upgrade Flarum to version 1.8.16 or later. This is the version in which the fix is claimed to be included.
  • Upgrade command (PHP/composer):
    composer update flarum/core --with-all-dependencies
    php flarum migrate
    php flarum cache:clear
    
  • Verify the patch: After the upgrade, check the SavePasswordController source code to confirm that expiry validation is now present, e.g., a check such as if ($token->created_at->diffInHours(now()) > 24) { throw new ...; }. If the check is missing, the patch is incomplete.
  • Test the patch: Trigger a password reset, wait 25 hours, then attempt to use the token. The request should fail with a token-expired error.

3. Long-Term Hardening:

  • Rotate all administrator passwords after applying the fix, in case any previously intercepted reset tokens exist.
  • Enable MFA for all forum accounts, particularly moderators and administrators, to reduce the impact of any future credential theft.
  • Regularly audit the password_tokens table for tokens older than 24 hours that remain active — a sign of an attempt to use expired tokens.
  • Subscribe to Flarum's security advisories and monitor the project's GitHub release notes for any additional vulnerability patches.
  • Ensure the forum's mail server configuration uses TLS and that password reset emails are sent only to verified, non-disposable email domains.

References

  1. NVD — CVE-2026-39923: https://nvd.nist.gov/vuln/detail/CVE-2026-39923 (Primary source; contains the vulnerability description and the claimed fixed version 1.8.16)

  2. Flarum GitHub — Release Notes for v1.8.16: https://github.com/flarum/framework/releases/tag/v1.8.16 (Pending confirmation; check here for the official fix commit and changelog entry)

  3. CWE-324 — Use of a Cryptographic Primitive with a Risky Implementation: https://cwe.mitre.org/data/definitions/324.html (Weakness categorization for the expired-token acceptance flaw)

  4. FIRST.org — EPSS (Pending Score): https://www.first.org/epss/ (The EPSS score for CVE-2026-39923 has not yet been assigned; this page will provide a real-time risk metric once available)

  5. CISA Known Exploited Vulnerabilities Catalog: https://www.cisa.gov/known-exploited-vulnerabilities-catalog (CVE-2026-39923 is NOT currently in the KEV catalog; if added, a deadline for patching will be set)


Threat Actor Campaigns: As of this report date, no threat actor campaigns specifically targeting CVE-2026-39923 have been observed in the wild. The vulnerability is not in the CISA KEV list, and no exploit code has been publicly released. However, the trivial nature of the post-token-exploitation (a single HTTP request) combined with the high impact of administrator account takeover makes this a high-priority candidate for future weaponization. Security teams should prioritize patching before such weaponization occurs.

◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2026-39923/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.