Can CAPTCHA Prevent CSRF? Not by Itself.
By Adrian Lăpădat
February 9, 2022
Your website could be vulnerable to well-hidden attacks that can do a lot of damage to users and their trust: Cross-Site Request Forgery (CSRF).
CSRF, also called XSRF and pronounced “Sea-surf”, is when a malicious entity takes advantage of an authorized web session and submits requests to the server while posing as the authorized user. CSRF is usually initiated through social engineering. CAPTCHA is a type of User Interaction (UI)-based CSRF Defense. CAPTCHA cannot prevent CSRF attacks by itself, and its implementation as UI-based CSRF Defense can leave users open to attack.
The concept behind UI-based CSRF Defense is that a website sets up a barrier requesting information only a user has access to. This type of defense should be used sparingly, as it is associated with lower conversion rates. It is best used as an additional security layer for when users attempt to change a password or make a financial transaction.
UI-based CSRF Defense is not a replacement for appropriate protections against CSRF like same-site cookie attributes and anti-CSRF tokens.
Although CAPTCHA can be used as UI-based CSRF Defense, it may not be a best practice, as it has a known vulnerability to CSRF.
A Brief Overview of CSRF
CSRF is dangerous because it is a common method of attack, dangerous enough to be on the Open Web Application Security Project’s (OWASP) Top 10 most critical application security vulnerabilities multiple times in a row. It was removed in 2017, which OWASP credits to developers’ increasing knowledge of CSRF as a vulnerability. Nevertheless, CSRF attacks continue to plague platforms’ security.
From a website engineer and user perspective, many CSRF attacks are especially troublesome because they can be undetectable.
From an attacker’s perspective, CSRF can help them stay undetected. An attacker targets state-changing requests, which are involved in changing passwords, financial transactions, and purchasing. These attacks look like normal user requests, making CSRF hard to detect.
You can test your web application (website) for CSRF vulnerabilities using audit tools like XSRF probe.
Common Protections Against CSRF
- Same-site Cookie Attribute | The browser prevents third-parties (other websites) from sending cookies, only accepting first-party cookies (cookies from the website itself).
- Anti-CSRF tokens | Tokens should be unique per user session, secret, and unpredictable. They should not be transmitted through cookies. Your framework may have anti-CSRF tokens by default, such as .NET or Sails.js.
You may read a more detailed overview of CSRF and these protections here. In addition, OWASP has a cheat sheet for preventing Cross-Site Request Forgery, which is a more in-depth technical overview.
Beware! Cross-Site Scripting and Login CSRF
If your application or website does not have proper Cross-Site Scripting (XSS) defenses, even perfect CSRF defenses are compromised. This is because XSS can reveal everything on a page to the attacker. That includes anti-CSRF tokens, which would make them useless; if an attacker knows them, they can easily bypass any anti-CSRF tokens meant to stop them.
Login CSRF is when an attacker forges a login attack to a website, logging the user into a website as the attacker. Therefore, it is important to have CSRF protections even at login.
CAPTCHA and Preventing CSRF
Most CAPTCHA work like this: first, the browser requests a challenge from the CAPTCHA provider. Then, the browser retrieves the challenge or image along with its identifier, called its challenge ID. The server receives the challenge ID and the data from the user. If they’re a match, the user passes.
One serious vulnerability is that an attacker could gain access to the challenge ID if it’s stored in the user’s browser. Then, they could use that ID to request a challenge from the CAPTCHA provider and solve it themselves. Afterward, they would make a CSRF request back to the server, which would include their solution and the challenge ID.
The server would then retrieve the request, validate it, and accept the malicious entity’s action. This is possible because the core principle of CAPTCHA is that the server does not know who solved the CAPTCHA, only that it has been solved.
These vulnerabilities do not only stop at common CAPTCHA systems, but apply to reCAPTCHA systems as well. Every current instance of Google reCAPTCHA, for example, shares this vulnerability.
Implement strong, session-dependent CAPTCHA—If the CAPTCHA’s value is stored in the server, and the CAPTCHA is displayed in a form tag, an attacker should not be able to retrieve the value.
Fortunately, there are other ways to implement identity reauthorization. Besides CAPTCHA, OWASP suggests re-authentication and one-time tokens, which can be utilized alongside single sign-on (SSO).
Consider implementing humanID—humanID is an SSO which can be implemented as a secure UI-Based CSRF defense. Our platform uses SMS to validate users via a one-time code. Since the message is sent to a user’s phone, attackers cannot use CSRF to bypass this defense mechanism.
humanID ties a user’s number to a salted hash for maximum security. Once we receive a phone number, we delete it immediately. The user’s phone number, and therefore account, is tied to the hash, but the hash cannot be tied back to the user. This means that user identity is not tied to their personal information, all without having to remember another potentially vulnerable password.