Cross-Site Request Forgery (CSRF) generates many questions from prospects, customers, partners, and Web application security professionals we work with. The questions tend to fall into similar categories, so we figured it would be helpful to summarize them and share our perspective on CSRF. We would definitely appreciate feedback and/or debate from the community to help battle-test our approach.
The 5 Most Often Asked Questions about CSRF
Basically, CSRF has a legitimate use-case to access almost every resource − from pages to forms − on most websites. Yet from a security perspective, we are only interested in the abuse-cases.
So how do we distinguish between the legitimate use-cases and the abuse-cases for CSRF?
At WhiteHat we define CSRF as a vulnerability when an attacker can execute CSRF against any of three types of resources:
1. Where security decisions are made.
2. Where an attacker can use CSRF to force arbitrary code injection that impacts one or more users.
3. Where a transaction occurs involving the transfer of money or goods.
Examples of decision-making processes that compromise security include:
Examples of CSRF forcing arbitrary code injection:
Examples of compromised transaction processes:
Compared to most design flaws, CSRF typically has a larger subjective “grey area” when defining which CSRF are vulnerabilities. We often find that a CSRF flaw requires more explanation in order for businesses to understand how CSRF puts their websites at risk compared to other design weaknesses. Consequently, the above definitions help us focus on – and give customers an understanding of – the CSRFs that can have a negative impact on their security and their business.
CSRF is clearly a “Design Flaw / Business Logic” vulnerability or, from a software perspective, an error of omission at specification time. Specifications that address security abuse-cases are commonly omitted – in the password-reset CSRF example we provide below – the missing specification is “only authenticated Entity actors should be able to reset their own passwords.” Given the context of omission – and given DAST’s strength at finding errors of omission – CSRF is most easily identified by Dynamic Analysis Software Testing (DAST). While it is possible to identify weak design-patterns in source code, such as the password-reset example, we find in practice that the majority of dangerous CSRFs are not identified by either Static Analysis Software Testing (SAST) or human source-code reviews.
It appears DAST Web application vulnerability scanners approach CSRF in one of three ways:
1. False-Negatives (FN): Do not test for CSRF.
2. False-Positives (FP): After scanning a website for vulnerabilities, attempt to replay every request reporting all successfully replayed requests – both idempotent and non-idempotent − as “Potential CSRF” regardless of security impact.
3. False-Negatives + False-Positives: Attempt to replay all non-idempotent POST requests/forms, and flag all successful replays as “CSRF Vulnerabilities.”
The second important FN gap is that scanners fail to identify CSRFs that facilitate arbitrary code execution. This is particularly a problem in the case of persistent code injection, which can be used to make XSS/CSRF worms such as the Samy Worm on MySpace.
False positives: The two scanner approaches just mentioned generate a massive amount of false positives for scanner users to sort through as they look for the proverbial “vulnerable needle in the haystack.” We’ve learned that most users eventually turn off the CSRF testing features; otherwise, they find themselves overwhelmed with many more results than they can possibly sort. Recently, a few scanners have tried to “tune down” the number of false positives, using some form of keyword signature matching in order to filter the false positives and raise their potential priority. This is actually one of the approaches that Sentinel uses, and has shown some merit.
WhiteHat’s Sentinel Service uses a combination of automation and customized tests generated by engineers in our Threat Research Center (TRC) to test for CFSR. Because CSRF is a business logic issue it is handled under the testing domain of our Sentinel Premium Edition (PE) service. One of the unique features of Sentinel PE is that our TRC engineers map out the application and teach Sentinel how to navigate logic and workflows, as well as how to create user comparison tests that usually reach across multiple users and multiple roles.
During this initial testing process we flag key areas that meet our three “actionable” CSRF criteria defined above and test them for replay-ability. As part of the ongoing scanning process, Sentinel PE also identifies new code and opens tickets that TRC engineers use to custom configure Sentinel in order to test those functions. Because most CSRF occurs in forms / POST requests it is relatively easy to capture these new functions and new features as they are released in the Web application. Of course detecting vulnerabilities in new code as it is pushed requires scanning the application on an ongoing basis.
WhiteHat also reviews every application covered by Sentinel PE service on a yearly cycle to determine whether new design patterns or coding practices have been introduced that Sentinel might otherwise overlook. For example, a new type of Web-remoting library could expose an application to CSRF without Sentinel automatically detecting it. Therefore, our standard practice is to customize and configure Sentinel for all sites we assess whenever a new design pattern or programming practice is identified.
On to Sentinel automation – specifically: automating the detection of Weak Design Patterns. During the past four years we’ve learned a lot about CSRF while testing thousands of Web applications. One of the discoveries is that some CSRFs occur in common, weak design-patterns that can often be described with a high degree of accuracy. For these cases we’ve built an automated battery of “Known Bad CSRF conditions” that Sentinel searches for. As an example, let’s consider the obvious password-reset design:
If Sentinel discovers a password-reset function that has only two input fields that both accept the same input and can be replayed, there is an extremely high likelihood that the function is CSRFable with clear security implications. Likewise, this same pattern will flag the section in a new-user account registration workflow, which is private to the user-session and located where the user first creates a password. In some cases the initial password-creation function can be re-invoked via CSRF, and then used to reset the user’s existing password after the account is created.
There are several other examples, similar to the one just described above, where describing the replay criteria is fairly straightforward once you know the name of the form or function involved in the decision / transaction.
Most anti-CSRF controls involve embedding a Dynamic Authorization Token (DAT), a token that is a one-time-use, mathematically unique nounce, into each request. Presumably, users who have not legitimately requested a page would not have the DAT required to successfully submit a CSRFable form on that page. However, if any part of the Web application is vulnerable to XSS or HTTP/RS, then an attacker can bypass the CSRF protection. For the sake of specificity, let’s call an HTTP/RS vulnerability in a resource that facilitates XSS: “XSS++”.
Specifically, the attacker will first force the victim to make a CSRF request to the XSS/++ vulnerable website, injecting the attacker’s XSS/++ attack code into the application. That XSS/++ attack will then execute in the victim’s browser, making a CSRF request to the protected resource, and will then parse the DAT required to make the protected request from the response. Finally, the attack will resend the malicious CSRF request, including the DAT that is intended to protect it. In effect, XSS/++ neuters the effectiveness of token-based CSRF compensating controls.
Because the attacker can force a legitimate user to CSRF an XSS/++ attack anywhere in a Web application, it is essential to remember that all XSS/++ are equally vulnerable to the attacker in this scenario. If the victim is logged in, it does not matterif the XSS/++ vulnerability requires authentication. And it does not matter if the XSS/++ is persistent or reflected. What does matter is to know this: All XSS/++ can be attacked equally. While persistent XSS can certainly have a larger impact over time, in regards to this specific attack scenario, all XSS attack vectors are equal.
Let’s wrap up this section with a concrete, real-world example of how a seemingly “benign” CSRF can be combined with other vulnerabilities, including XSS, to completely compromise a system. Here are the parameters: A website has no obvious CSRF vulnerabilities, but it is vulnerable to XSS, and has a Local-File Include vulnerability that potentially could allow arbitrary server-side code execution. The vulnerable application also includes a “file-upload” feature, but because you cannot CSRF the file-upload cross-domain, most scanners will ignore this particular CSRF. However, the attacker can combine CSRF + XSS + the Local File Include vulnerabilities to completely compromise the website, the Web server, and the operating system − remotely − in this scenario.
Here’s how it’s done: A user of the vulnerable website visits another website that the attacker has already hacked. The hacked website forces the user’s browser to make a CSRF attack that injects an XSS attack payload into the vulnerable website. The XSS attack fetches the attacker’s malicious PHP file, uploads it, and then exploits the Local File Include design flaw to execute the malicious PHP file on the server, taking complete control of the system − a system that appeared free from CSRF attack. All of this malicious activity occurs without the attacker making a single click, and the victim is completely unaware that anything has happened. In this manner, a seemingly innocent CSRF can be combined with other potential and known vulnerabilities to produce disastrous results.
Given these facts, if you have CSRF vulnerabilities that present real risks, it is tactically imperative to fix all of your XSS and HTTP/RS vulnerabilities while simultaneously building your CSRF protections. It is equally important to have both an ongoing website risk measurement and testing program that can identify new XSS and HTTP/RS that appear in new code as it is released, as well as a process in place to remediate the new vulnerabilities quickly. Otherwise – your CSRF vulnerabilities will always be exploitable – and your Window of Exposure to CSRF in your Web applications will be open “All Year Long.”
There are other ways to improve both software designs and development processes in the SDLC in order to reduce XSS, XSS++, and in the CSRF in new code you write. However, that subject in itself is vast and requires a longer discussion.
In summary, for the purpose of measuring and managing risk to your organization from CSRF in applications that: (1) you own; (2) you control; (3) you don’t own; (4) and/or that you can’t control, you must have − at a minimum − an ongoing tactical Web security measurement and response program for CSRF, XSS, and XSS++.
Comments or questions? Disagreements? Fire way, below: