fix: #3558256 Security: Any CAPTCHA can be replayed

Closes #3558256

Root cause: After captcha_validate successfully validates a CAPTCHA response, it sets token=NULL in the DB to prevent replay attacks. However, the captcha_token hidden field rendered in the HTML still contains the old (now invalidated) token. On the next submission, _captcha_get_posted_captcha_info compares the posted token (old) against the DB token (NULL), they don't match, triggering "CAPTCHA session reuse attack detected", which creates a new session with a random solution that can't match the user's response.

Fix (two parts working together):

  1. captcha.module captcha_validate(): For SHOW_ALWAYS persistence, skip the status != SOLVED filter when querying the solution, since the session must remain readable across multiple submissions.
  2. Captcha.php preRenderProcess(): For SHOW_ALWAYS persistence, regenerate the token in both the DB and the element's hidden field during pre-rendering (which runs after validation but before HTML output). This ensures the rendered form always has a valid token that matches the DB for the next submission.
Edited by Adam Nagy

Merge request reports

Loading