The Sneaky Facebook XSRF/CSRF!
TL;DR: A CSRF vulnerability that could reset a Facebook user’s post-by-email address was hidden deep inside the Facebook mobile site, where you have to first trigger some kind of legacy browser fallback support and then to tweak with some parameter(s) to catch it!
As you know, Facebook (and many other web services) does provide a post-by-email address that you can use to upload photos, videos or to post status updates to your account right from your email easily. That address is particularly useful in cases in which direct access to your Facebook account is not possible at the time….
So, while I was messing around on (m.facebook.com), specifically with this image uploading endpoint (https://m.facebook.com/photos/upload/), I forwarded a malformed form submission to that endpoint where some
POST key/value pairs were omitted and some others were duplicated and tampered with, just to see how Facebook would handle such
POST request … and to my surprise, Facebook responded with a 302 HTTP status code pointing to:
1 Location: https://m.facebook.com/photos/upload/?email_fallback
Where an error message was suggesting me to upload my photos using my post-by-email address instead, as my browser doesn’t seem to be supporting posting photos directly! Here’s how that page looked like at that time:
And as you can see from the screenshot above, there’s a “Reset Email Address” button which is when clicked, it submits a
POST request containing an anti-CSRF token named “fb_dtsg” and a parameter named “reset_email” assigned the value of “1”; the obvious hunt here is to omit that “fb_dtsg” parameter—or to alter its value—and then forwarding the request, right?
Unfortunately, that didn’t work and the token was being properly validated … not until I came up with an outlandish idea “what if I submit that very parameter using a
GET request instead of
POST?”, so I eventually forged this simple
1 GET https://m.facebook.com/photos/upload/?email_fallback&reset_email HTTP/1.1
And guess what? My post-by-email address got simply reset, thanks to 12 chars added to a