Monday, June 18, 2018

Cross-Site Request Forgery in Plain Language


Cross-Site Request Forgery, commonly known as CSRF, is one of the most well-known web security attacks. I first studied it in a college classroom, and since then I've mostly worked at big companies where safety was often baked into the frameworks most software engineers used. This week I brushed off my dusty knowledge, and in the process realized there is a lack of explanations of common attacks in plain language.

I'll start with one issue, CSRF. This isn't mean to be comprehensive, but hopefully will augment other resources. This post will outline the problem and is meant for a general nontechnical audience.

Browser Background


To understand CSRF, you first need to know a bit about web browsers. Notice that when you log into a website, from then on, the website seems to "know" it's you who is browsing it. You can continue to click from page to page without being asked to log in again and again. How does this work?

This works because of a browser feature called cookies. On a basic level, a cookie is a piece of information that a website can send to your browser when you visit it, and the website can metaphorically ask to store that information on your device. You can configure your browser to reject cookies, but by default most browsers accept and store them.

From then on, browsers follow two rules:
  1. Whenever you access a website that sent you cookies, the browser will send back whatever cookies that website stored on your device.
  2. The browser will only send cookies that came from Website A back to Website A; it will never send cookies that came from Website A to Website B.

Note: none of the above is magic. It is how browsers are expected to behave. When you use Chrome or Safari, you are trusting that Google or Apple have correctly implemented those rules.

Let's go back to the example of logging into a website. Here's what happens behind the scenes, on a high level:
  • After you send your username and password to the site, the site verifies your username/password, and sends back a set of cookies that essentially says, "This certifies we know you are YOUR-NAME-HERE." Importantly, it's hard to forge these cookies.
  • On each subsequent request to the website, your browser sends back that set of cookies, which stands in place of your username/password to identify you.

You can imagine it would be pretty bad if an attacker got access to your cookies and could then impersonate you. This is the logic behind Browser Rule #2 above, and underlines the trust you are placing in your browser.

However, the point of CSRF is, an attacker doesn't even need to get your cookies.


CSRF: The What


In CSRF, an attacker tricks you into taking an action, identified as you, without you intending to do that action. To give a physical example in the same spirit: it reminds me of this phone scam where a caller asks you, "Can you hear me?" The attacker records you saying "Yes", and then uses that "Yes" fraudulently as proof you wanted to buy some product you didn't actually agree to. You protest, "But that's not what I meant when I said 'Yes'!" However, you did say 'Yes'—that is your voice.

CSRF has a similar structure, except the thing used to identify you is your cookies, not your voice. Let's assume you are logged into a website we'll call MyBank.com. Thus, your browser has stored the cookies set by MyBank.com that say "This certifies we know you are YOUR-NAME-HERE." Remember that whenever the browser makes a request to MyBank.com, it will always send those cookies that identify you.

So if the attacker wants you to take an action on MyBank.com that you would not knowingly want to do, they need to come up with a way to make you send a request to Website A without you knowing it. A plausible request you would not want to make is "Send $100 to Account-Owned-By-the-Attacker." The question is, how do they convince you to make a request you don't want to make?

Importantly, you don't need to have MyBank.com open in a browser tab in order for your browser to make a request to it. A malicious page can contain code that executes "Make a request to Website A that sends the attacker money." So the short answer to the above question is: the attacker gets you to visit a site, or open an email, that contains malicious code, while you are logged into MyBank.com. They cannot guarantee that when you visit the malicious page, you are logged into MyBank.com at the same time. But if you happen to be, then the attack can succeed.

In the worst case, it is really that simple—you open a harmful website or email, and you've been hit. And most of the time you will not even know, because the harmful website or email is disguised to look harmless.

Prevention


As an end-user, you can try not to click on sketchy emails or visit malicious sites, or any sites that might have embedded sketchy code. In practice, this is tough to do, and most of us simply trust that MyBank.com has implemented standard safety checks to prevent this kind of attack from happening on it.

The key behind the protections is this: Remember above, I said "you don't need to have MyBank.com open in your browser in order for your browser to make a request to it." That is true, but a website that is properly protected will only allow requests that were made on the website proper to succeed. It will detect that requests to it made from other locations are not legitimate, and cause those requests to fail. So, if MyBank.com is well-protected, an attacker can still make you visit a malicious website that makes a request to MyBank.com that says "Send $100 to Account-Owned-By-the-Attacker," but MyBank.com will recognize that this is not a request you made from MyBank.com and disregard it.

How does MyBank.com do this? I'll save this for a later post. There are a few different solutions, but the summary is again: you are putting your trust into the fact that your web browser is properly implementing security policies, and that MyBank.com is properly implementing these prevention techniques. As the end-user, an important thing to understand is what entities you are implicitly trusting.

1 comment: