Web applications need to take great care to accept only legitimate requests. A forged request can result in theft of money, changed passwords, and loss of confidential data. A favorite trick of criminals is to submit a link or form that looks like one from the website but has maliciously changed parameters. This technique can do serious damage if it hits an administrative account.
The attack's name is Cross Site Request Forgery or CSRF (sometimes XSRF). A malicious site uses it to attack a legitimate site where the victim is logged in. It performs actions which the victim could perform but wouldn't want to.
How CSRF works
The attacker gets the user to open the malicious page, perhaps through a phishing email. The user might not have to do anything more than view the page. It sends a forged request to the target site. Typically the target is one that's popular enough that it's likely some users will be logged into it. Alternatively, the attack may be aimed at people who are known to use a certain site (e.g., employees of a company).
Suppose the target is a banking site which lets users transfer funds to another account. A request that tries to steal money might look like this, where 123456 is the thief's account:
That's a very naive attack, but it illustrates the concept. No site should ever allow a GET request for actions that have side effects, especially real-world ones. It should use a form and require a POST request. It should use HTTPS in the request. Those precautions won't prevent CSRF, but they're necessary preconditions to stopping the attacks.
Requiring a POST request eliminates some avenues for the attack. The forger will need to do better than an anchor or IMG tag with a URL. However, creating a POST request that imitates a form submission isn't hard at all.
Part of the problem is that all cookies issued by a site are, by default, sent back to it with every request. The impersonator gets to ride on the site's own cookies.
As a general principle, any request that comes from a browser should be untrusted unless it can be verified. A request to a site doesn't necessarily reflect the user's intent.
Using SSL (HTTPS) for all sensitive pages and forms is the first step. It won't stop malicious requests from coming from the browser, but it will prevent alteration of pages or form data by a man-in-the-middle attack. Any site that asks a user to log in should take this precaution.
With that as a base, there are a number of ways to stop most CSRF attacks. The two most popular ones are nonce tokens and the double submit cookie method.
A nonce token is an arbitrary value sent by the server to the browser. The browser inserts it as a parameter into the POST request when it submits a form, and the server checks that it's the correct value. Browsers follow the same-origin policy, which says that data held in a particular page is accessible only to pages that have the same origin. A script on www.example.com/page1 can access the browser data for www.example.com/page2 but not the data for www.anotherexample.com. This makes the nonce value safe from discovery in most cases. It's not safe against same-page CSRF attacks.
Another method is to give the same nonce value in a cookie and a token. Again, the browser puts the token into the POST request. The server checks that the submitted token and the cookie match. The server doesn't have to save the token value, which makes the approach more convenient in some application environments.
CSRF attacks work because any request to a site normally delivers all cookies associated with it. A recent expansion to the cookie protocol offers another layer of protection. The SameSite cookie parameter directs the browser to limit or forbid the sending of cookies when the request comes from a page that doesn't belong to the same site as the destination. Two values are allowed.
- SameSite=strict directs the browser to send the cookie only if the source and destination belong to the same site.
- SameSite=lax makes an exception for top-level GET requests, i.e., those that operate at the address bar level.
This provides good protection against CSRF in browsers that support it. However, it didn't gain widespread adoption until 2018, so many older browsers will ignore the SameSite attribute. It should be treated just as an extra layer of defense, not as strong protection by itself.
CSRF and XSS
These defenses are effective only if the attack is truly cross-site. Hostile scripts which are injected into a site are much harder to stop. They appear to originate from the same page, so they can access tokens and cookies. When cross-site scripting (XSS) sets up CSRF, the same-origin policy gives no protection, so defending against it is very difficult.
The best answer is to do everything possible to prevent XSS. Allow third-party content onto a page only when it's really necessary. Rendering untrusted content safe is a complicated matter which is beyond the scope of this article. A page which includes forms to perform sensitive actions should not allow third-party content unless it's highly trusted.
Stopping CSRF with a Web Application Firewall
Strong security uses multiple defenses. Preventing CSRF requests from getting through is an important part of the strategy. Quttera's Web Application Firewall detects threats which come from known malicious sources or follow suspicious patterns. Quttera WAF, as a part of small & midsize business cybersecurity solution, guards against many threats, including shell code, SQL injection, and improperly formed paths. Keeping malicious requests from getting through protects your business and your customers.