Problem/Motivation
During a security audit we see that we can pass through the math captcha, so people can by example create a lot of account in user/register without problems.
Steps to reproduce
- last Drupal 11.x
- last captcha 2.0.9
- captcha math enabled on register form
- settings persistance "Always add a challenge."
- fill manually the user/register form a first time, capture the submission as a curl request with your browser, in my case , it was:
curl --location 'http://drupal.docker.localhost:8000/user/register' \
--header 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \
--header 'Accept-Language: fr-FR,fr;q=0.9' \
--header 'Cache-Control: no-cache' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Origin: http://drupal.docker.localhost:8000' \
--header 'Pragma: no-cache' \
--header 'Referer: http://drupal.docker.localhost:8000/user/register' \
--header 'Sec-Fetch-Dest: document' \
--header 'Sec-Fetch-Mode: navigate' \
--header 'Sec-Fetch-Site: same-origin' \
--header 'Sec-Fetch-User: ?1' \
--header 'Upgrade-Insecure-Requests: 1' \
--header 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36' \
--header 'sec-ch-ua: "Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "Linux"' \
--data-urlencode 'mail=myemail@mail.fr' \
--data-urlencode 'name=myemail@mail.fr' \
--data-urlencode 'form_build_id=form-jXfnUG_wp4F9U-TxiWldEBP7wbu10dBTbnH--otV7tc' \
--data-urlencode 'form_id=user_register_form' \
--data-urlencode 'captcha_sid=5' \
--data-urlencode 'captcha_token=E-h0TOLXtWXUpelA5BM9FqPPOnQ9cFtzpqj0yXclvek' \
--data-urlencode 'captcha_response=8' \
--data-urlencode 'op=Create new account'
- change the email in the curl request, here myemail@mail.fr by myemail2@mail.fr , launch several times the request, the captcha will be valid ramdomly if you put a response between 1 and 20 (here i let 8) . Maybe first time or after 15-30 trys.
Proposed resolution
Avoid that a captcha response can be replayed, use a one time captcha token ?
Issue fork captcha-3558256
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
tichris59 commentedComment #3
tichris59 commentedComment #7
grevil commentedTest LGTM! Other failing tests are unrelated. I created a separate issue for this: #3567905: Fix failing tests.
The test here suggests, that we should delete the token after captcha_validate() is called. Although this is the most secure approach and will definitely resolve this issue, it will probably cause some UX Issues:
@japerry should decide, if and how this should be fixed.
Comment #8
anybodyUnsure if this is really critical, as Math Captcha is kind of "funny" in times of AI (and even before it was more kind of a demo level).
Comment #9
grevil commented@anybody, even though Captcha Math is mentioned here, I think it also applys to other captcha types (the failing test also uses captcha type "test" not "math").
But I still agree I don't see it as "Critical", as the user has to at least get the captcha correct once. He can't get around the captcha entirely.
Comment #10
grevil commentedRegarding the UX issues in #7, after these issues are confirmed, we could also make a setting out of this, e.g. ("Delete captcha token after validation", Default TRUE).
We should also check what the behavior is with the multistep form captcha validation turned on.
Comment #11
alexboss commentedDear maintainers / developers,
Thank you for your feedback and considering fixing the issue.
Indeed, there are some constraints, but can´t they be overcome ? For instance:
Not really an issue IMHO, this happens rarely, and even if it does, it´s already the case on many registration / contact forms.
Isn´t possible to disable the submit button once it has been submitted once or a validation process is ongoing ? Plus, if it has been submitted at least once (first request) and went through successfully, then it´s fine.
Yes, that´s true. But the problem observed is that once a form has been submitted with a valid captcha, then it's really easy to copy the submission as a cURL request and litterally flood / spam the contact forms with hundred of automated submissions. This should be prevented.
Thank you and best regards.
Comment #12
joevagyok commentedAny captcha method can be skipped with this, not only Math Captcha.
Comment #13
joevagyok commentedComment #14
anybodyNice @joevagyok that looks clever. We should fix #3567905: Fix failing tests first I think to see real test results here?
Comment #15
grevil commentedAgreed. especially since the "max PHP" and "next minor" pipelines now fail compared to the pipelines in #3567905: Fix failing tests.
Unfortunately the tests are probably not fixed in a few minutes...
Comment #16
alexboss commentedThanks @joevagyok for the fix https://git.drupalcode.org/project/captcha/-/merge_requests/124/diffs?co...
Having tested on my ends, it completely blocks the recording of submissions using cURL / session replay attacks.
Amazing job, thanks !
Comment #17
joevagyok commentedThe failing tests issue is green now. Please review it so we can move this forward!
Comment #18
anybodyRTBC once tests are green
Comment #19
anybodyWhile tests are now green in #3567905: Fix failing tests it's still failing here.
Comment #20
grevil commentedComment #21
joevagyok commentedComment #22
anybodyThanks @joevagyok!!
Comment #23
grevil commentedJust some textual changes to the comments. Otherwise this LGTM!
Comment #25
grevil commentedComment #27
grevil commentedThanks everyone, I tagged a new release: https://www.drupal.org/project/captcha/releases/2.0.10.