In our dialogues with customers, we often come across cross-site request forgery (CSRF) findings marked as False Positives due to having CAPTCHA implemented. There is a widespread misconception that having CAPTCHA in place protects against CSRF. In most cases, this is incorrect at best and dangerous at worst. CAPTCHA does not prevent CSRF – here’s why.
CAPTCHA or Completely Automated Public Turing test to tell Computers and Humans Apart, is a challenge prompt that appears, asking you to prove you are human by reproducing distorted letters and numbers into a box to complete your form request. Click here for further explanation.
To understand why CAPTCHA does not guarantee CSRF protection, let’s look at how it works:
On the client side:
- The browser requests a challenge from the CAPTCHA provider.
- The browser retrieves the challenge/image and the ID of that image.
- The user solves the challenge/image by transcribing it into an input field.
- When the user clicks submit, the browser sends the challenge ID and the transcribed data to the server.
On the server side:
- The server receives the challenge ID and the transcribed data from the user.
- The server forwards these two parameters to the CAPTCHA provider that in turn confirms if it was correctly solved or not.
The server never knows who solved the CAPTCHA, just that it has in fact been solved. This is the core principle of all CAPTCHA systems.
An attack scenario would look like this:
- The attacker requests a challenge from the CAPTCHA provider.
- The attacker saves the challenge ID and solves it.
- The attacker compiles the CSRF request and includes both the solution and challenge ID in the request.
- The server retrieves the request from the user, confirms it is a valid solution, and accepts the action.
(Google uses a slight variation on this. The user sends a request to Google as soon as they have solved the CAPTCHA and the received token is then sent to the website for validation, but the result stays the same.)
This is nothing new. Egor Homakov described this exact attack scenario back in 2013 and he was not the first to have done so. It’s possible to buy challenge:solution pairs online from people that have already solved them, making this attack even more practical.
The official OWASP page has recommended implementing a CAPTCHA for a long time, so it is not surprising that CAPTCHA is believed to be a solution. OWASP vaguely mentions that CAPTCHA needs to be implemented correctly, but this is easily misinterpreted.
While challenge-response is a very strong defense against CSRF (assuming proper implementation),
We often iterate this same attack scenario explanation to our customers that report CSRF findings as false positives to demonstrate that implementing CAPTCHA is not enough. We also receive questions about the next version of Google reCAPTCHA and whether it protects against CSRF attacks.
Neither CSRF or Cross-Site Request Forgery yield any results in the documentation for Google reCAPTCHA. This is important because even if it turned out to actually protect against CSRF right now, relying on it for all future sessions can be risky. The way reCAPTCHA works could be changed anytime and because the documentation does not mention CSRF protection, Google is not obligated to ensure reCAPTCHA works as a CSRF defense.
Even though reCAPTCHA is not intended to protect against CSRF, we decided to take a closer look. Debunking the myth of reCAPTCHA as CSRF protection was as easy as looking at the official documentation.
The secret is static for all solved CAPTCHA’s on your website and therefore also not relevant for this question. The only thing that matters is the response, and possibly the optional remoteip. Note that the same verification process is used for both reCAPTCHA V2 and Invisible reCAPTCHA, so this ‘problem’ is universal. Note that this is not a criticism of Google reCAPTCHA as their goal has never been to prevent CSRF attacks in the first place.
It would be possible to use the remoteip which would make a CSRF attack much more difficult as the attacker and the user would have to use the same IP address. However, this is not something we would recommend as it also prevents legitimate scenarios where a user, for example, receives the CAPTCHA over a mobile connection, automatically connects to home wifi and thereafter submits the actual request over that connection.
We can hereby conclude that reCAPTCHA and CAPTCHA do not prevent CSRF by default, and assert that the vulnerability to CSRF attacks needs to be monitored even though these modules are in place.
Check if you’re vulnerable to CSRF by running a free Detectify security scan.