Problem/Motivation

The CAPTCHA module's captcha_sessions table has a sid column that is meant to contain the user's session ID (if present). Drupal core's (since 7.x) session ID column has a length of 128 characters, but captcha_sessions.sid is limited to 64; this makes it possible for a logged in user to run into fatal errors when CAPTCHA attempts to insert their up-to-128-char SID into the captcha_sessions table (such as #3151110: Fatal Error: Captcha session_id too long ).

I stumbled into this issue recently, getting the fatal error Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'sid' at row 1: INSERT INTO "captcha_sessions" ("uid", "sid", "ip_address", "timestamp", "form_id", "solution", "status", "attempts") when loading a Webform in Drupal 11.3 with CAPTCHA 2.0.10.

Fixing the table locally solved my issue:
ALTER TABLE captcha_sessions MODIFY sid VARCHAR(128) NOT NULL DEFAULT '';

Steps to reproduce

  1. Log in with a session ID larger than 64 characters (e.g. with session hash function sha512 or session.sid_length=128)
  2. Attempt to access a Webform protected by CAPTCHA

Proposed resolution

Bump the captcha_sessions.sid column length to 128 characters.

Remaining tasks

None.

User interface changes

None.

API changes

None.

Data model changes

Column captcha_sessions.sid altered to VARCHAR(128).

Issue fork captcha-3631101

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jay.dansand created an issue. See original summary.

jay.dansand’s picture

jay.dansand’s picture

Issue summary: View changes

japerry made their first commit to this issue’s fork.

japerry’s picture

Drupal core does not generate session IDs itself: PHP does, and `session.sid_length` can be anything up to 256. So a site with a long session ID configured hits "1406 Data too long for column 'sid'" on MySQL.

Widening the column to 128 (as in the first commit on MR !144) would not cover a 256-character ID. Core's own `sessions.sid` is 128 wide, but it never stores the raw ID: SessionHandler writes `Crypt::hashBase64($sessionId)`, a fixed 43 characters. That is the approach I've taken here:

  • `captcha_sessions.sid` now stores `Crypt::hashBase64(session_id())`, or "" (empty string) when there is no session. This always fits the existing 64-character column, so no schema change or hook_update_N is needed, and the session credential is no longer stored in plain text.
  • The column widening and `captcha_update_8908()` are reverted. That also avoids an update-number clash with other open MRs.
  • The new post update `captcha_post_update_clear_plain_session_ids()` blanks the raw IDs already stored. The module never reads this column; it is only written.
  • The new kernel test `CaptchaSessionIdTest` covers a 256-character session ID, no session, and the post update. On MySQL it fails against the old code with the exact error reported here.
japerry’s picture

Status: Active » Needs review