In some cases we get a "CAPTCHA session reuse attack detected." in our logs. I suspect that this could i some cases be due to the fact that the user have spent a long time on the site before submitting the form. Eg. reading a lot of text first.
The standard setting for PHP session.gc_maxlifetime is 1440 seconds. Also the table holding the sessions "captcha_sessions" is purged via cron, where records older than session.gc_maxlifetime are deleted.
So if a user loads a page with captcha (we are using the Math captcha) and spends a lot of time on the page. Then decides to submit something it is possible that cron has already run, and deleted the users corresponding record with token information related to the captcha. The captcha module then responds with a "CAPTCHA session reuse attack detected." message.
The user has to spend more than 1440 secods on the page, but then this could happen.
Issue fork captcha-3488136
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
Comment #2
rene bakxI have the same issue at a website with a rather big multistep form and did noticed a older closed issue (https://www.drupal.org/project/captcha/issues/3423309) that most likely is related to this issue as well.
The default services.yml set's that value to
gc_maxlifetime: 200000so that timeout should not occur at all, but that is not always the case!If you run your cronjob's via drush, that services.yml is not loaded and the default value is
session.gc_maxlifetime => 1440 => 1440Running the cron every 5 minutes, gives a rather big change of triggering deleting a session that is still in use, as this module uses the value from PHP. This can be easily checked by adding single line to the captcha_cron() method
Drush cron logs : Captcha cron max life time 1440
Browser/curl/wget cron logs: Captcha cron max life time 200000
Multiple options to fix this issue.
Personally I would opt-in for making the delete time configurable in the Captcha module itself with a default value being the value from ini_get('session.gc_maxlifetime'). Doing this would not be a breaking change, and it makes sure the value is consistent with the core session garbage collection as this is triggered by PHP’s session system during normal web requests,
The other option would be to change your PHP settings globally to the same value as set in services.yml, but that is not possible on all hosting providers.
And lastly you could opt-in to run the cron using the wget/curl approach, but that has it downsides when running in a walled or airgap environment.
So no hard solution, but an open discussion about the approach for this issue.
Comment #3
vmarchukComment #4
vmarchukThank you for reporting the issue! I think we have the same annoying problem, but it's hard to say yet.
We'll try using the code from MR that I opened and see if that helps. This shouldn't break anything or have any side effects.
I will report the results after using the patch for some time.
Comment #6
anybodyTests are failing?
Comment #8
japerryThe diagnosis in #2 is right and MR !136 reads the container parameter instead, which is the right fix. I rebased it onto current 2.x and added a commit to clean it up a little:
Fixed!