Alert Logic Blog

‹ Back to Our Blog

Facebook Phone Abuse (The Tale of the Missing Rate Limit)

October 10, 2012

Intro

There was a recent media frenzy over the latest FaceBook privacy issues, initiated by Suriya Prakash and further intensified by myself. There has been a lot of media coverage on this topic in the past few days, and this blog post is meant to clear up some questions or events regarding the issue.

Privacy Issue

It’s been known for a while that anyone can look up a phone number on Facebook under “Find Friends” and receive the supplied real name back for that entry. This has been used often in public blogs/sites to troll [1] or for general information gathering. To reduce the scope of abuse, Facebook implemented rate limits on the amount of these queries possible within a given time period. While this was true through their main interface, they seemed to have forgotten about it somewhere else.

The Forgotten Limit

On October 1, a friend named Suriya Prakash informed me of an issue with rate limiting on the mobile frontend for Facebook. As many of you may know, mobile counterparts have been a continuously successful playground for attacks, including FaceBook [2]. Suriya decided to inform FaceBook through their White Hat bounty program and, hopefully, receive compensation for discovering the issue. After much talk between Suriya and the FaceBook security team, team responded on October 2 that a rate limit was in effect and that this was a non-issue. After creating a macro and attempting to prove to issue one last time, Suriya decided to go the full disclosure route [3]. Having worked with the White Hat team before, I know that it takes some work to get the responders to understand the full implication of the reported vector, so I decided to write a more effective proof of concept tool to light a fire under the situation. After all, sometimes seeing is believing.

Enter facebook-hit.py (I’m not a creative man)

Well, Sunday came around I decided to take an hour and write up a proof of concept tool to abuse this “feature”. The interface for pulling a number was nice and easy as there was no nonce token or other dynamic value to further complicate the procedure–just a simple GET interface. By querying m.facebook.com/search/?query=<number>, I could pull and parse the result from the page. I decided to use my previous experience in concurrent programming to make this process as fast as possible. A lot of articles came out stating that it used 10 or up to 10 concurrent search requests at a time. Well, this is actually a user-definable value and you could pass it an option to do as many as you wanted. This is truly concurrent, not thread-based, so it doesn’t worry about the Python GIL and the kernel scheduler allows the processes to span cores. I only used 10 as a default because that ended up as one result every second on average. During my hour of testing I was doing chunks of 50-150 number ranges. I closed in on 1000 number requests, if not more, during the short testing phase.

After testing the proof of concept and ensuring all of the options worked (user provided range of numbers, user provided file of numbers, amount of concurrent processes, wait periods, etc.), I decided to publish the project on Google Code and give it to the public [4]. Within hours, I was getting information back from people using the script. Many were having fun crawling tens of thousands of numbers by using a larger amount of concurrent processes with a couple of different Facebook accounts (about a 10k range each account). This achieved much more than one result every second.

The Response

After a day of the script’s release, I was contacted by a reporter at 7:30pm CST Monday. Then on Tuesday, I started seeing posts everywhere about it. This was probably one of the best things that could have happened from a defense perspective, as it seemed to have lit a fire under Facebook’s security team. The initial release of the script had a check to see when the account may be banned (or you were D(D)os’ing the server) by checking for HTTP status return responses like 3xx, 403, 5xx, etc. so it didn’t fail silently. Because of this a user was aware immediately and reported back to me saying they were getting accounts locked out:

“Trying to lookup a 10k range no longer works. After… a few hundred (at most) you get logged you out with the following message.

‘Your account has been temporarily suspended We have detected some suspicious activity coming from this IP. As a security precaution, your account has been temporarily suspended.’
‘Reactivation You will have to wait 24 hours to get back into your account.’”

I received this message on Tuesday at 10PM CST. This was an incredibly quick turnaround! It appears the media helped expediate the fix by a tremendous amount of time.

The Result

I was surprised by the amount of Facebook users that had phone numbers tied to real names. Within a block of 150 numbers (at 1 result/second), I got back a surprising amount of results. I guess the 2-factor authentication that they worked so hard to push was a real success! Another issue was not only that a real number returned back, but the Facebook id as well. I think Bogdan Botezatu said it best:

“Unlike e-mail messages or blog comments, approaching a user by phone is much more effective in a spear vishing [voice phishing] attack, mostly because the computer user is not aware of the fact that his phone number may have ended up in the wrong hands. Coupled with the users information in their profile, an attacker can convince the user into handing personal information in no time.”

Voice phishing attacks and other type of phone scams are common and their success rate is already high, Botezatu said.

“Now imagine that these crooks address you by your full name and back up their statements with information about you taken straight from your [Facebook] profile.” Botezatu said.” [5]

Of course, I was personally having fun seeing corporate network phone ranges and finding those who tied their Facebook to a corporate/work number. An interestingly large amount of people did this (if anyone else is curious enough to check it out).

Aftermath/Future

Well, now it’s time to test how Facebook handles rate limits. Ironically, some of the test accounts required a phone number to validate the registration. On my initial run I was able to procure 300 results before they locked my account for 24 hours; there’s a good solid number to start testing the rate limit. I decided to take on two more tests to see if there was a faulty implementation.

The first test was to check if they locked accounts by a session value. This involved completing 200 lookups, logging out and back into the account, and then attempting another 200. I would repeat this cycle until I cleared 1000. This test, however, got the badboy (dedicated to you software cracking people out there) account locked message.

Then it was time for a timer test. I already received tester responses saying minute-sized wait periods did not seem to bypass the rate limit, so I had to expand from there. I decided an hourly scale was the best way to start. The process included completing 200 requests one hour, then 200 the next hour to see if it cycles every hour or less. If this test suceeded, then I would slowly reduce it by 10 minutes and do another 200/200 test to figure out when they cycle or for how long the counter lasts.

However, when I tried this on Wednesday at 10am CST, I had the badboy lockout message within a minute. From a short testing period, it seems they are doing HTTP header checks (mine doesn’t send typical headers like referer or useragent). A further guess is it involves the referer field and/or how the interface is now accessed. When I queried just the GET interface with a few numbers in my browser, the account got locked. I will update this post as soon as I find more details.

Conclusion

Quite honestly, I’m still not sure why an account name or Facebook id needs to be attached to a phone lookup result. It should only give an option to send a friend request by that number if it existed, like you would with an email. I do believe the rate limit has been fixed now, as of 10 AM CST on Wednesday I could only do 10-30 requests before getting the badboy account lockout. However, if this is done by referer field and my original 300 still works, then I believe the rate is still to high and harvesting is still a viable option.

You also have to give it up to the media on this one. Seriously, a couple of months of back and forth turned into a couple hours to cook up a patch as soon as the media got a hold of it.

~Written by Tyler Borland of AlertLogic ACID

References

[1] http://www.geeksaresexy.net/2012/10/06/this-guy-will-never-accidentally-text-the-wrong-person-ever-again/ – FaceBook Number Trolling

[2] http://theharmonyguy.com/oldsite/2011/04/21/recent-facebook-xss-attacks-show-increasing-sophistication/ – Other mobile FaceBook attack

[3] http://suriya.me/me-and-facebook-a-cautionary-tale/ – Suriay Prakish FaceBook Report Tale

[4] http://code.google.com/p/facebook-phone-crawler/ – Concurrent FaceBook Phone Crawler Script


[5] http://www.pcworld.com/article/2011396/facebooks-phone-search-can-be-abused-to-find-peoples-numbers-researchers-say.html – Statement from Bogdan Botezatu

Comments

  1. Alert Logic Security Intelligence

    UPDATE:

    They were indeed doing simple HTTP referer and/or useragent checks. I am able to do 299 in an hour, 300 will result in a block. There are other methods that are available that still do not do any rate limiting. These methods have been privately reported.

    UPDATE 2:

    A real fix has been pushed out and you can no longer corellate a phone number to a real name. You can only send a friend request for a provided phone number now.
    http://arstechnica.com/security/2012/10/facebook-moves-to-keep-phone-numbers-for-two-factor-protection-private/

Leave a Reply

Your email address will not be published.
Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2010-2013