Cross-Site Request Forgery

Learn about cross-site request forgery, same-site cookie, and using components with known vulnerabilities.

What is CSRF?

Cross-site request forgery (CSRF) used to be a bigger issue than it is now. These days, most web frameworks automatically include defenses against it. But a lot of old applications are out there. Some are vulnerable targets, while others can be used as stooges.

A CSRF attack starts on another site. An attacker uses a web page with JavaScript, CSS, or HTML that includes a link to our system. When the hapless user’s browser accesses our system, our system thinks it’s a valid request from that user. Boom,your user is roasted. Note that the user’s browser will send all the usual cookies, including session cookies. Just because the user appears to have a logged-in session doesn’t mean the request is intentional. The first thing to do is make sure our site can’t be used to launch CSRF attacks. XSS is a common trap. If the attacker can supply input that we display without proper escaping, the attacker can trick people into viewing it through our site. Second, make sure that requests with side effects, such as, password changes, mailing address updates, or purchases, use anti-CSRF tokens. These are extra fields containing random data that our system emits when rendering a form. Our code expects to get the same token back when the user submits the form. If the token is missing or doesn’t match, it means the request is bogus. Most frameworks today do this for you, but we might have to enable CSRF protection in our service’s configuration.

SameSite cookie

We can also tighten up our cookie policy with the relatively new SameSite attribute 16^{16}. A cookie with that attribute looks like this in a response header:

Set-Cookie: SID=31d4d96e407aad42;

SameSite=strict

The SameSite attribute causes the browser to send the cookie only if the document’s origin is the same as the target’s origin. That includes subdomains, so same-site cookies for account.example.com would not be sent to images.example.com. Not every browser supports same-site cookies as of June 2017. The Chrome family supports it on desktop and mobile. Opera does as well, but Firefox, Internet Explorer, and Edge do not. Keep an eye on the Can I Use, website to see when our supported browsers have this feature 17^{17}.

Same-site cookies are not a zero-cost feature. In particular, they may require you to change your session management approach. A top-level navigation request (an in-bound link from another system) on a new page is not a same-site request when the cookie says “strict.” The RFC recommends using a pair of cookies:

  • A session “read” cookie: not same-site that allows HTTP GET requests
  • A session “write” cookie: same-site strict that required for state-changing requests

As with the other top 10 items, OWASP has a cheat sheet for CSRF prevention 18^{18}.

Using Components with Known Vulnerabilities

Is there anyone out there running Struts 2 between version 2.3.0 and 2.3.32 or 2.5.x before 2.5.10.1? Beware of an attack that allows remote code execution 19^{19} . That’s what got Equifax. Once you know that vulnerability exists, it should just be a matter of updating to a patched version and redeploying. But who keeps track of the patch level of all their dependencies? Most developers don’t even know what all is in their dependency tree. Sadly, most successful attacks are not the exciting “zero day, rush to patch before they get it” kind of thing that makes those cringe-worthy scenes in big budget thrillers. Most attacks are mundane. A workbench-style tool probes IP addresses for hundreds of vulnerabilities, some of them truly ancient. The attacker may just collect an inventory of targets and weaknesses, or they may run automated exploits to add the machine to a growing collection of compromised minions.

It’s important to keep applications up-to-date. That means coming to grips with our dependency tree. Use our build tool to extract a report of all the artifacts that went into our build. (Don’t forget about plugins to the build tool itself! They can also have vulnerabilities). Keep that report someplace and check it once a week against the latest CVEs. Better yet, use a build tool plugin that automatically breaks the build if there’s a CVE against any of our dependencies 20^{20}. If that’s too much work, sign up for a commercial service like VersionEye 21^{21}.

Many vulnerabilities never get published, though. Some are discussed on the project’s mailing list or issue tracker but do not get CVEs, so keep an eye on those as well.

Get hands-on with 1200+ tech skills courses.