What is Cross Site Request Forgery (CSRF) and how can it be avoided?

In simple terms, CSRF is misusing the "saved" trust a website has in your browser. Often your token for authentication will be stored in a cookie. When a browser creates a request for a website it automatically sends all persisted cookies for that website along with the request. Which basically means that any request sent from your browser will appear as if it was from you. Of course you would have to have logged onto the site at some point. But just imagine how rarely you have to log on to facebook. You are authenticated for a very long time on most sites.

Simply, a CSRF exploit uses the authenticated state in your browser to execute something unwanted. Such as a money transfer or posting without your consent.

I will go through some of the cases here.

How it can be done

The attacks come in many different variations. It can be as simple as a website misusing the http verb GET. A GET request should be safe to use at all times - It should not change anything on the serverside. w3 states that "the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe""

However it is up to the creator of the website to adhere to this standard. Meaning a GET request easily can be implemented as a POST - changing information on the server. All the information for a CSRF attack using GET requests must be within the url. Like the request below (totally made up btw):

Normally you would not be allowed to change my name like above. However if you somehow made me go to that link, and I was already logged in. Then the get request would succeed without a problem - that is - if no protection against CSRF is in place. Let's say it was a little bit more serious like a money transfer or buying something online. That would be terrible.

How would someone execute this? Well a simple technique would be to put the get request within the src of image on a site or perhaps send it in an email. The browser would automatically try and request (GET) the image. Another attack vector would be a simple old-school http form with a post. However you would have to trick the person into submitting it - using social engineering of some sort.

Something to note is that the "attacker" will never get the HTTP response. Meaning he or she will not get the data from the responses. This is all about executing something on the serverside in your name.

Counter measures

I will mention two counter measures against CSRF attacks here.

The CSRF token

Usually implemented as a unique key associated with a user's session. The key should never be saved or read from a cookie as that will just be sent to the server. It should be stored on the page of the site as a hidden field. When you make http requests this token should accompany the request as a header (in some cases a query parameter will do).

Why is this more secure? Because the attacker will never have the CSRF token. The tactics I showed you above are only valid with reusable URLs. Without the CSRF token the request should be rejected. When the user actually browses the site the token should be added to the header.

Check the origin and referer header

You can assure that the request comes from the same origin (your website) by checking the origin and/or referer header. This header will contain the domain/url from where the request is sent from. Yes this header can be changed by scripting but there is no way to do so in the examples above. Which means you should deny requests which are not originating from your site.

Most browsers already implement this through the same origin policy.

Wrapping it up

CSRF is not that hard to counter. By not misuing the HTTP GET verb you will already be very far. But simple counter measures like the two above can secure your users (yes not you, your users) against this attack.