Slashdot Mirror


CSRF Flaws Found On Major Websites, Including a Bank

An anonymous reader sends a link to DarkReading on the recent announcement by Princeton researchers of four major Web sites on which they found exploitable cross-site request forgery vulnerabilities. The sites are the NYTimes, YouTube, Metafilter, and INGDirect. All but the NYTimes site have patched the hole. "... four major Websites susceptible to the silent-but-deadly cross-site request forgery attack — including one on INGDirect.com's site that would let an attacker transfer money out of a victim's bank account ... Bill Zeller, a PhD candidate at Princeton, says the CSRF bug that he and fellow researcher Edward Felton found on INGDirect.com represents ... 'the first example of a CSRF attack that allows money to be transferred out of a bank account that [we're] aware of.' ... CSRF is little understood in the Web development community, and it is therefore a very common vulnerability on Websites. 'It's basically wherever you look,' says [a security researcher]." Here are Zeller's Freedom to Tinker post and the research paper (PDF).

9 of 143 comments (clear)

  1. Very nasty by Twigmon · · Score: 5, Informative

    This looks like a very nasty attack to defend against. More info:

    http://en.wikipedia.org/wiki/Cross-site_request_forgery

  2. Details and Examples by nmb3000 · · Score: 5, Informative

    For anyone curious, Jeff Atwood of Coding Horror recently wrote about them in his blog. Included are some additional details and a couple of examples.

    At face value it's a somewhat obvious exploit, but still interesting.

    --
    "What do you despise? By this are you truly known." --Princess Irulan, Manual of Muad'Dib
    /)
  3. Hanlon's Razor by A+non-mouse+Coward · · Score: 5, Insightful
    I think Hanlon's Razor is in play here.

    Never attribute to malice that which can be adequately explained by stupidity.

    Don't assume these people don't care or don't want to fix it. CSRF is in the class of "WebAppSec" (what the kids call it these days) that is not "syntactic" in nature; meaning that you cannot just say "here, use this API and you're safe". It's a "semantic" problem; the developer has to both understand "how" sensitive transactions can be abused AND "how" these transactions can be fixed (like with a nonce).
    It's probably just that they don't know how to do it, at least not manageably on an average budget.

    --
    libertarian: (n) socially liberal, financially conservative; neither left, nor right.
  4. Re:Computer systems need security audits. by zobier · · Score: 5, Insightful

    Repeat after me boys and girls "GET requests shouldn't change anything on the server".

    --
    Me lost me cookie at the disco.
  5. Transfer money where? by z0idberg · · Score: 5, Informative

    including one on INGDirect.com's site that would let an attacker transfer money out of a victim's bank account

    With my INGdirect account (in Australia) you can only transfer your savings back into your normal bank account that is associated with the ING account. So I don't think an an attacker could actually transfer money out to somewhere they could get it. Associating another bank account with the ING account requires more than just logging in to your ING account (phone/written permission etc. IIRC).

    The attacker would be able to cause some inconvenience and will get your bank account number etc. but I can't see how they would actually get your money.

  6. Re:Computer systems need security audits. by TheLink · · Score: 5, Interesting

    GET requests in practice change stuff on the server. Making everything POSTs is just annoying - you get all those "click OK to resubmit form" messages and you don't even know what form it is.

    What they should do is sign urls (at least for significant stuff), so you can't just iframe a static url, you have to guess the correct url - which should change at least on a per session basis.

    e.g. instead of http://slashdot.org/my/logout it should be something like http://slashdot.org/my/logout?salt=123955813&sig=01af85b572e956347a56

    Where sig=sha1(concat(user session,salt,site secret,site time in hours))

    If sig doesn't match, you try to see if sig matches the time that rolled over:
    sig=sha1(concat(session,salt,site secret,site time in hours-1))

    user session = random string+primary key.

    For stuff that should not be resubmitted, you use another param to enforce that.

    --
  7. Stopping CSRF attacks by this+great+guy · · Score: 5, Insightful

    [A pseudorandom token] doesn't really stop it. All it does is reduce the problem to a cryptographic attack -- which is subject to brute force.

    Saying that is like saying "cryptography doesn't really provide privacy, because it is subject to brute force". Of course pseudorandom tokens stop CSRF attack (when implemented properly).

  8. Re:Computer systems need security audits. by spec8472 · · Score: 5, Insightful

    While GET does in practice change stuff on the server, the idea is that it should be repeatable without adverse effect.

    So, calling GET on a document might increase a hit counter, or update some other information - having me repeatedly call that function again should be safe.

    However using GET for Updating Account Details, or Moving money (just some purely /random/ examples) is just plain bad design.

    The example of signing GET requests is useful in some situations, but *mostly* not necessary if the design is right.

  9. Re:Computer systems need security audits. by tuma · · Score: 5, Informative

    GET requests in practice change stuff on the server. Making everything POSTs is just annoying - you get all those "click OK to resubmit form" messages and you don't even know what form it is.

    I agree that the "click OK to resubmit form" messages are annoying - and dangerous, because your average user has no idea what the message means, or what the implications might be of clicking OK.

    Fortunately, there is an extremely simple paradigm that works beautifully:

    1. When an HTTP request is going to change something on the server, make it a POST request.
    2. The server receives the POST request, and updates internal state, etc. When it is finished handling the internal changes (either successfully or not), it does NOT print an HTML page. Instead, it prints a REDIRECT message telling the web browser the next page it should GET. (You're the author of the web app, so you can build whatever ultra-specific URL you want here.)
    3. The web browser GETs the specified page and displays it, showing whatever HTML you deem to be appropriate as the result of the POSTed change.

    At the conclusion of this interchange, the user's browsing history only contains the GET page that was displayed before the POST, followed by the GET page showing the results. They can freely use their forward and back buttons to navigate within their history with no ill effect, and they will never see a "resubmit form?" question from their browser.

    I use this paradigm 100% of the time. You receive tremendous benefits by respecting the documented/intended behavior of GET/POST (e.g. no problems with caching or prefetch, and when a user intentionally resubmits a POST operation it will truly be resubmitted to the server), without the painful "resubmit form?" redux.

    --
    If you lived on /. , you'd be home now!