Everyone with a Magento store will recently have seen the notification that a possible CSRF attack against the Magento admin interface has surfaced. I thought I would take this opportunity to give a quick overview to CSRF(Cross-site request forgery) attacks, particularly how they work against web administration panels such as Magento and ways to protect Magento and other web applications from these sort of attacks.
The CSRF Basics
The easiest way to explain the attack is to think about what is happening under the hood when you are navigating a web page. You browser makes requests to the remote server for content, and to manipulate data stored on the server. In a strict RESTful approach to web applications, your browser will make GET requests when you are reading information and POST or PUT requests when you are creating or updating information.
A GET request is what your browser does when you click a standard link or when you type a web address into your address bar. These GET requests happen when your browser requests other resources too, such as images, CSS files and javascript files.
A POST request most commonly occurs when you submit a form from a web browser, though a form doesn’t always have to POST. I say most commonly because with javascript you can cause POST requests without the user having to submit a form. It’s important to bear this in mind as we progress through the worked example below.
So when all the hackers are tucked up in bed, the internet ticks along nicely like that. The problem is, there needs to be a way of knowing who is making requests to avoid malicious users making fake requests. At the same time we do not want to have to authenticate ourselves on every single request we make, it would be tedious.
That is why we login to websites, so that we can get a special token called a cookie, which we keep sending back to the server that gave it to us. The cookie is like an key that we are given when we prove to the server who we are. For example when you make a GET request to your bank, provided your cookie hasn’t expired then your cookie is sent to the bank, who will (provided they match it with a live session on their servers) let you into your account.
The good news for you is, if you just finished at your blog site then rushed over to my blog to read all about Magento Virtual hosting on MAMP without logging out of the blog site, you will not send that all important cookie to me, because browsers only send these cookies to the sites they came from. phew!
Well, not quite. Even though I don’t get the cookie, I do know that your browser has the cookie, and will continue to send it to the blog when it makes requests. What if my website, forces your web browser to make a request to your blog site? What if I embed a form like the one below in my blog page then trick you into submitting it? What if I don’t even trick you, I just force your browser to do it?
<form action="www.yourblog.com/update-details"> <input name="email" type="hidden" value="me@myemail.com" /> </form> |
What if I then also made a request that told your blog to reset the password because it was forgotten and send it to the blog email address? Who will get the email? Your blog would think you were doing those things, when in fact it was me controlling your browser. This is the nature of a cross site request forgery attack. You trick the browser into making requests on behalf of an authenticated user to a site which it has access to, even if the user does not want these requests made.
Protection against CSRF attacks in Magento
There are two common ways to protect against CSRF attacks.
1) Check the referer header in the request
When your browser makes a request it usually adds a header named ‘referer’[sic] (yes that is referrer with only one ‘r’) which tells the destination server which URL you have come from (very big brother). The destination server could check that for all important GET or POST/PUT requests the referer is itself, if it is not then the request must have come from a different website.
The issue is that not all browsers use the header, and some people (they are easily identifiable by their large tinfoil cone hats) disable it for privacy reasons. So it is not going to work all the time, but it surely is easy to implement.
2) Ensure all requests are guarded with an additional server generated parameter
Another option is to include a server generated code or key with each request originating from a server generated page. What I mean by that is if the server generates HTML for a form, it should include a hidden input variable in that form that contains a special short lived key(tied to your cookie). When a form is submitted to the server it can check the key in the request matches the key it generated and if they do not, the request can be ignored. Any other web server could not generate the correct key, so could not send fake requests.
This is harder to implement properly, but for example, in Java applications can be handled by filters that inspect outbound requests for certain HTML (forms, links etc) and alter them to include these keys. Likewise inbound request filters can then check the requests contain the keys, and reject the requests if they do not.
Magento thankfully already employs some of these techniques to prevent CSRF attacks. I am sure that in the near-term the developers will be enhancing security to include these techniques in all places. Right now though, you will have to make do with a simple workaround. By changing the URL of your admin interface you can avoid malicious attacks because the attacker won’t know what URL to send the fake requests to. Unless of course they pick it up from your referer header!