Description
Punk::Plugin::TOTP versions before 0.05 for Perl allow the second-factor attempt limit to be reset by replaying an earlier session cookie because the challenge route counts failures in the session.

The POST handler on challenge_path keeps the failure count as tries inside the totp_pending record in the session, raising it on each rejected code and deleting the pending record once it reaches attempts, five by default. Punk::Session carries the session in a signed cookie unless the application declares a store, and keeps no server-side record, so an earlier value of the same session stays valid until the expiry stamped inside it. A client that saves the cookie before its failed attempts and presents it again gets the pending record back with its counter, and the limit never fires. The replayed record is accepted while its own expiry, pending_ttl seconds from the challenge and 300 by default, has not passed.

Sessions declared with a store are not affected: the pending record and its counter then live server-side.

The attempt limit does not bound guessing of the second factor, which is left to the per-address rate limit the plugin registers on the same path, 30 requests per 60 seconds.
Published: 2026-08-25
Score: 9.1 Critical
EPSS: < 1% Very Low
KEV: No
Impact: Bypass OTP retry limit
Action: Immediate Patch
AI Analysis

Impact

This vulnerability is a session replay flaw (CWE-307, CWE-642) that allows an attacker to reset the OTP failure counter, enabling repeated guesses of the second factor. The Punk::Plugin::TOTP module keeps the OTP failure counter inside the signed session cookie when no server‑side store is configured. An attacker who captures a session cookie that contains a pending OTP challenge can replay that cookie before it expires, resetting the counter to a low value and preventing the internal limit from incrementing. This allows repeated attempts to guess an OTP without ever reaching the plugin’s attempt threshold. The vulnerability is therefore a form of replay attack that undermines the second‑factor enforcement.

Affected Systems

The issue is found in the Punk::Plugin::TOTP module used by Perl web applications. All releases prior to version 0.05, including 0.04 and earlier, are affected because they rely on Punk::Session without a server‑side store. The fix requires upgrading to 0.05 or later and adding the columns that store the failure count (totp_failed and totp_failed_at by default) to the user table.

Risk and Exploitability

The CVSS score is 9.1, indicating high severity, and the EPSS score is <1%, with the vulnerability not listed in the CISA KEV catalog. The attack requires an attacker to possess a valid session cookie that contains a pending OTP challenge; the cookie expires after the configured pending_ttl, 300 seconds by default, giving the attacker a limited but sufficient window for replay. Even with the plugin’s per‑address rate limit of 30 requests per 60 seconds, an attacker can cycle through OTP guesses within that quota, effectively bypassing the second‑factor retry limit. Because the vulnerability allows repeated guessing of the second factor, it poses a moderate to high risk for systems that rely on this plugin for two‑factor authentication. The risk is higher in environments where the failed OTP counter is not persisted outside the client side.

Generated by OpenCVE AI on August 26, 2026 at 21:50 UTC.

Remediation

Vendor Solution

Upgrade to Punk-TOTP 0.05 or later, and add the two columns the count is kept in to the user table (totp_failed and totp_failed_at by default, named by fields).


Vendor Workaround

For deployments that cannot upgrade to 0.05, declare the session keyword with a store, which needs a Punk::Cache backend shared between workers. The cookie then carries only an opaque id and the counter is out of the client's reach.


OpenCVE Recommended Actions

  • Upgrade to Punk‑TOTP 0.05 or later and add the totp_failed and totp_failed_at columns to the user table
  • If an upgrade is not possible, configure Punk::Session to use a server‑side store (e.g., a shared Punk::Cache backend) so that the counter is not stored in the cookie
  • Verify that the per‑address rate limit on the OTP challenge path remains active or enforce an additional rate limit to reduce the number of guesses an attacker can make

Generated by OpenCVE AI on August 26, 2026 at 21:50 UTC.

Tracking

Sign in to view the affected projects.

Advisories

No advisories yet.

History

Wed, 26 Aug 2026 19:30:00 +0000

Type Values Removed Values Added
Metrics cvssV3_1

{'score': 9.1, 'vector': 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N'}

ssvc

{'options': {'Automatable': 'yes', 'Exploitation': 'none', 'Technical Impact': 'total'}, 'version': '2.0.3'}


Tue, 25 Aug 2026 23:30:00 +0000

Type Values Removed Values Added
References

Tue, 25 Aug 2026 21:30:00 +0000

Type Values Removed Values Added
Description Punk::Plugin::TOTP versions before 0.05 for Perl allow the second-factor attempt limit to be reset by replaying an earlier session cookie because the challenge route counts failures in the session. The POST handler on challenge_path keeps the failure count as tries inside the totp_pending record in the session, raising it on each rejected code and deleting the pending record once it reaches attempts, five by default. Punk::Session carries the session in a signed cookie unless the application declares a store, and keeps no server-side record, so an earlier value of the same session stays valid until the expiry stamped inside it. A client that saves the cookie before its failed attempts and presents it again gets the pending record back with its counter, and the limit never fires. The replayed record is accepted while its own expiry, pending_ttl seconds from the challenge and 300 by default, has not passed. Sessions declared with a store are not affected: the pending record and its counter then live server-side. The attempt limit does not bound guessing of the second factor, which is left to the per-address rate limit the plugin registers on the same path, 30 requests per 60 seconds.
Title Punk::Plugin::TOTP versions before 0.05 for Perl allow the second-factor attempt limit to be reset by replaying an earlier session cookie because the challenge route counts failures in the session
Weaknesses CWE-307
CWE-642
References

Subscriptions

No data.

cve-icon MITRE

Status: PUBLISHED

Assigner: CPANSec

Published:

Updated: 2026-08-26T18:44:53.718Z

Reserved: 2026-08-24T23:12:17.196Z

Link: CVE-2026-78655

cve-icon Vulnrichment

Updated: 2026-08-25T23:07:24.336Z

cve-icon NVD

Status : Deferred

Published: 2026-08-25T22:17:06.537

Modified: 2026-08-26T20:18:03.050

Link: CVE-2026-78655

cve-icon Redhat

No data.

cve-icon OpenCVE Enrichment

Updated: 2026-08-26T22:00:04Z

Weaknesses
  • CWE-307

    Improper Restriction of Excessive Authentication Attempts

  • CWE-642

    External Control of Critical State Data