Should I include CSRF protection on a login form?

Since I found Angel’s “Plain English” series of blog posts so helpful when I was first learning about different kinds of vulnerabilities on the web, I wanted to continue that series. I hope to expand into some of the nuances of more commonly known vulnerabilities, and touch on some of the less well known ones. Let’s get started with one special case that I often find questions about: CSRF on a login form.

To start, if you’re not familiar with the Cross Site Request Forgery (CSRF) attack, you should definitely give Angel’s blog post from a few years ago a read. In the typical way of thinking about a CSRF, an attacker is able to submit a form on behalf of a victim with data the attacker controls. In the classic example, you can imagine an online service that allows users to transfer money between each other, perhaps by first adding their credit card. In the absence of any protective measures against CSRF, the attacker can trick their victim into clicking a link that submits a form on their account, and transfers money into the attacker’s account.  However, what if our humble service is aware of this risk, and includes some form of CSRF protection on all of their authenticated forms? Our attacker will have to get a bit more clever, and though the aforementioned example might often be the most dangerous case, it is not necessarily the only one.

Strictly speaking, a CSRF attack is one where an attacker is able to submit any request on behalf of the victim. So, the attacker begins looking for other ways to trick our poor victim, and finds that the login form is totally unprotected. Hatching a devious plan, our attacker crafts an attack that would submit the login form in the victim’s own browser, thus logging them into the attacker’s account. So our victim -- now perhaps only slightly confused as to why their credit card info is missing -- adds all of their personal information necessary to send money to their friend, and logs out, thinking nothing more of it. Now our attacker, having full control over their own account, logs back in to find that they have everything they need to siphon funds from our poor victim.

As you may have noticed, the impact of an exploit like this varies from site to site, depending a lot on how likely or possible it is for a victim to leave behind personal information. It also relies on tricking the users into completing at least one extra step, instead of just clicking a dubious link. However, the world of security frequently involves accounting for even very unlikely cases, because an attacker will often have hundreds or sometimes thousands of opportunities, and doesn’t need to succeed every time. It’s also worth mentioning that even seemingly harmless vulnerabilities can be leveraged to enable more potent attacks. You might already be able to imagine how one could use an attack like this to direct a user to a page with an injected XSS, but perhaps I’ll save that concept for a later blog post.

For these reasons, I like to err on the side of caution, and avoid giving an attacker the opportunity to exercise any functionality on another user’s behalf. For more information on how we suggest you implement your CSRF protection, you can refer to the article linked above.

I hope you found this short post helpful in understanding some of the nuance of one of the most threatening types of vulnerabilities on the web. I’m one of the support engineers here at Tinfoil Security, so if you have any thoughts, feel free to email me at dallas@tinfoilsecurity.com. I’d love to hear your feedback!


Dallas Weber

Dallas’ detail orientated nature makes him very passionate about helping customers get the most out of their product experience by solving any of their challenges. Outside of cybersecurity, he has a particular curiosity for how movies and video games are designed. Dallas studied Applied Mathematics at Robert Morris University.

Tags: plain english csrf


Cross-Site Request Forgery (CSRF) in Plain English

Welcome back to my weekly series where I explain different types of website attacks in plain English. So far, I’ve tackled two of the most common vulnerabilities on the web today: SQL injection and Cross-Site Scripting. Today, I’d like to talk about another common vulnerability that the Tinfoil scanner finds all too often: Cross-Site Request Forgery.

Cross-Site Request Forgery (CSRF or XSRF) is another example of how the security industry is unmatched in its ability to come up with scary names. The attack itself is quite simple. A CSRF vulnerability allows an attacker to force a logged-in user to perform an important action without their consent or knowledge. It is the digital equivalent of an attacker forging the signature of a victim on an important document. Furthermore, the attack leaves no evidence behind, since a forged request contains all of the information and comes from the same IP address as a real request from a victim.

The Danger

The most important actions that one can perform on a website also tend to be the ones that require one to log in to the website. Banks need to be able to identify a user to know the bank account from which to withdraw. E-commerce sites need a user’s identity so she can be associated with a credit card number, billing address, and shopping cart. Video-sharing sites need to be able to associate unique upvotes with users. Using CSRF, an attacker could force a victim to send the attacker some money, or buy something from them, or upvote their videos.

As an example, my banking website, example.com, does not protect itself against CSRF. You, an unsuspecting example.com user, also happened to be logged in to example.com. Now, malicious user Mallory sends you (and millions of other example.com users, of course) an HTML e-mail including the following tag.

<img src="https://www.example.com/transfer?amount=1000&amp;destination=mallory">

If you have a webmail client that loads images automatically, the transfer request will be made from your browser using your IP address and your example.com session cookies, exactly as if you made the request yourself. My bank website, therefore, treats this like a legitimate request and sends $1000 from your account to Mallory’s account. All evidence suggests you legitimately made this transaction from your logged-in browser.

If all actions on my site are vulnerable to CSRF, this could even lead to further damage. If the attacker can forge a password reset request, or an e-mail change request, the attacker could subsequently gain full control of the victim’s account. If the victim is an administrative user, the entire website would be under the attacker’s control.

The Answer

There are many ways to protect your website from CSRF, but in this post I will only discuss the most common and most effective solution. It is the solution used by many popular web frameworks, including Ruby on Rails. It’s called the Synchronizer Token Pattern.

For each user session, logged-in or otherwise, the Ruby on Rails server generates a unique token and stores that in the session cookie, which is additionally digitally signed server-side to detect tampering. The server then places this token as a hidden field into every form on every page that it renders. If a user submits the form normally, say, by clicking the “Submit” button, the token will be sent to the server as a form parameter, as well as in the cookie. The server then checks to see that the token in the cookie matches the token in the form parameter. If they don’t match, the request is assumed to be forged, the action is not performed, and the user is forcibly logged out. This only works on POST requests, so it is also up to you to ensure that all of the important actions that can be performed on your site are POST requests.

With this protection in place, if a malicious user attempts to use the same <img> tag trick from above to forge an important action, it won’t work for several reasons. Firstly, the request would be made via GET instead of POST, and the application just won’t accept it because Rails was told that this important action is only to be performed over POST. The attacker can, however, get around that with some clever uses of Javascript.

<img src="https://www.example.com/transfer?amount=1000&amp;destination=mallory" onload="...">

Using an onload handler, the attacker can dynamically create a form and submit it via POST. However, this runs into our main CSRF protection. Because the attacker does not know the secret token that needs to be sent with the request, the request will fail. Unless the website is vulnerable to other kinds of attacks, such as Cross-Site Scripting, the attacker has no way to obtain the secret token, and CSRF is prevented.

As always, if you have any questions about CSRF or other vulnerabilities on your website, feel free to get in touch with us. If you are looking for an automated way to detect CSRF vulnerabilities on your website, check out Tinfoil Security. Tinfoil provides the best web application security solution on the market, and it detects CSRF vulnerabilities on your website along with many other types of web vulnerabilities.


Angel Irizarry

Angel Irizarry is the Software Samurai of Tinfoil Security, and a self-proclaimed software purist. All he needs to do his best work is a plain Linux machine with Git and Emacs installed. He loves everything about front-end development, like making pages interactive and super fast, even if that means digging in and optimizing some SQL. When he's not writing code, which isn't very often, you'll find him on his iPad scouring his RSS feeds for news and rumors of cool new gadgets.

Tags: plain english csrf xsrf