Jump to content
  • Advertisement
Sign in to follow this  
  • entries
    375
  • comments
    1136
  • views
    298608

V5: XSRF Prevention

Sign in to follow this  
superpig

448 views

Looks like I just missed Gaiiden's weekly journal roundup. Oh well.

I've spent today and yesterday implementing a security measure against cross-site request forgery attacks, otherwise known as XSRF attacks. These are a slightly terrifying class of attack, not least because so few people seem to be paying attention to them; an estimated 70% of sites on the web are vulnerable to - and have done nothing to guard against - this kind of attack.

XSRF is an attack in which a malicious site causes your browser to make a request to another one, in such a way that it takes advantage of the fact that you've got some cookies or some kind of session key open with that other site.

Say you've got a banking website which allows you to conduct some transactions online. They've got a web form for sending money from your account to another one; it submits data to /actions/do_transaction?to=XXXX&amt=YYYY, where XXXX is the target account number and YYYY is the amount. When you're logged into the site, your session is maintained through the use of a cookie stored on your machine.

All that I have to do is embed a 1x1 image in my page that is sourced from '//your.bank/actions/do_transaction?to=1234&amt=1000', and if you view my page while you're logged in, then presto - you've transferred $1000 to account number 1234. Your browser sees the URI that the image is supposed to come from, and issues a request for it - sending any cookies necessary to keep the session alive. It's like 'remote controlling' a session - there's no need to ever actually steal the session cookie when you can just make the browser that already holds it do what you want to do. It's known as a "confused deputy attack

So, some protections that don't work:


  • Check the referrer: easily faked, plus some users don't send referrer headers.

  • Use POST requests instead of GET requests: while this would defeat the IMG tag approach, it's trivial to get around using javascript and XmlHttpRequest.

  • SSL: At no point is the connection between you and your bank site ever actually attacked in this, so securing that connection doesn't help.

  • Encrypted cookies: Again, the cookie is never actually stolen, so encrypting it won't help.



Ultimately, there is only one possible defence: Require that the request contain some information that is not stored in cookies and that malicious sites cannot know ahead of time. When your bank presents the 'transfer money' page, it includes that information in the page itself - in the HTML, or in the javascript - and submits it straight back again when you've finished filling out the form. So, if a malicious site wants to obtain that information, it can only do it while you've got the actual page open - and in theory the browser security model should prevent that.

As for the information itself, something as simple as a hash of the request URI with the session ID is enough to shut down most (if not all) attack scenarios. It's got the advantage of being easily testable - all the information you need is in the request itself.

So. What I've built over the past couple of days is a WCF extension that can test messages for the XSRF-prevention token prior to the message even reaching the service operation itself. In short, all I have to do is add a couple of attributes to my service contract:


[ServiceContract]
[XsrfAwareBehavior]
interface IDiscussionService
{
[OperationContract]
[WebGet(UriTemplate="", BodyStyle=WebMessageBodyStyle.Bare)]
Stream GetDiscussionOverviewPage();

[OperationContract]
[WebGet(UriTemplate = "activeTopics", BodyStyle = WebMessageBodyStyle.Bare)]
Stream GetActiveTopicsPage();

[OperationContract]
[WebGet(UriTemplate = "activeTopics.json", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
[XsrfAwareOperation]
GDNet.Discussion.TopicHeader[] GetActiveTopicsJson();

[OperationContract]
[WebGet(UriTemplate = "{id}", BodyStyle = WebMessageBodyStyle.Bare)]
Stream GetThread(string id);
}


You can see one of them at the beginning - indicating that this service contract needs to be checked for XSRF-aware operations - and then the actual operation marker on the GetActiveTopicsJson() method. XsrfAwareBehavior invokes a service contract behavior I've written, which scans the contract for methods marked as XsrfAwareOperation, and inserts my token-checker into the formatting pipeline for each one.

Actually inserting the tokens into HTML is still a bit clunky - I've got a method available to my XSLT which takes the URI for a link and returns the appropriate token. It'll do for now.

Note that this doesn't protect against script injection attacks. If somebody manages to run an unauthorized javascript on a page from actually within the site, then they'll have access to the cookie containing the session ID and could quite easily hash it themselves to issue requests elsewhere. V5 is not going to be quite as permissive as V4 is when it comes to custom javascript, though [wink]
Sign in to follow this  


2 Comments


Recommended Comments

Quote:
Original post by superpig
[...] Use POST requests instead of GET requests: while this would defeat the IMG tag approach, it's trivial to get around using javascript and XmlHttpRequest. [...]
You cannot use XmlHttpRequest across domains, though as this is enforced on the client's machine it could be compromised by a bug/security breach in their browser. I'd say any HTTP request that changes something should be done over POST, anyway. I know someone who had a whole bunch of files deleted when Google's spider followed all the "delete" links (using GET) on their page!

I agree that your method is better, though. [smile]

Share this comment


Link to comment
Well, OK, maybe not XmlHttpRequest, but how about an HTML <form> and a javascript which automatically submits it?

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!