Race conditions on the web
The goal of this blog post is to raise awareness about race condition attacks in both developers and security people, because I feel like not many know about this kind of bug - I have participated in CTFs whose points system was vulnerable to race conditions (even Facebook’s CTF platform was). All examples I wrote about were found in public bug bounty programs and are fixed.
At the bottom of the page is a compilation of tools and posts for further reading. Enjoy!
Stealing BitCoin from Cobalt.io
Cobalt is a bug bounty platform that offers payouts in BitCoin and PayPal. Their BitCoin withdrawal flow was vulnerable to a race condition attack which could be used to withdraw one bounty multiple times. Check out the original report here:
Confirming any unused email address on Facebook
This was an unusual race condition which could be exploited to confirm any unused email address on Facebook. During February, I was testing the mobile registration flow on Facebook, and somehow succeeded to confirm a random email address. I reported this to Facebook hoping they’d be able to debug it, since I did not understand how it happened, and made ~5000 requests before realizing the email was confirmed. On April 20th I re-tested the flow and finally got reliable proof of concept:
Register a new account, but do not confirm the email or phone
Obtain a Facebook-issued access_token for the new account
Create multiple requests at the same time toapi.facebook.com/method/user.editregistrationcontactpoint while changing the add_contactpoint POST parameter
you should change add_contactpoint between an email you have access to, and one you do not, for example [email protected] and [email protected]
On [email protected] you will receive a confirmation link that will look like this: /[email protected]&c=13475&code=84751
The GET parameter “c” is always the code for your email address, but the “code” parameter confirms the one you do not have acces to ([email protected]). After obtaining the code, you can go to Facebook settings and confirm the email.
The bug was fixed on May 10th, 2016, and is my favorite report to Facebook.
Adding multiple single-use coupons to one Facebook ad account
During the final three months of 2014, Facebook announced they’d be giving double bounties for any ads-related bugs, so I started poking around and found a (minor) bug in how they handled ad coupons. Some coupons can be used only once, and a single ads account should be able to redeem only one ad coupon. Using race conditions, I could add multiple ad coupons to a single account. Bear in mind that this bug did not enable me to re-use single coupon multiple times or on different accounts.
To exploit this bug, you would need to buy a couple ad coupons, and try to redeem them at the same time on one account. Multiple coupons would then be available for you to spend, which obviously breaks the one coupon per account rule.
The interesting thing about this report is the timeline:
October 20, 2014: Bug reported to Facebook
October 22, 2014: Facebook is looking into the issue
December 2014: Many messages back and forth between Facebook and me; they were not able to reproduce this issue.
I was at fault here, because the steps were not clearly explained in my report. Looking back, I should have attached my POST requests and server responses for easier analysis.
February 13, 2015: Update from Facebook, they still are not able to reproduce this, but have checked the code and believe vulnerability is present. Facebook apologizes for the high latency so far.
April 22, 2015: Facebook still not able to reproduce it. They ask me if the bug is still present. I have no way to buy coupon codes, and inform Facebook it is impossible for me to re-test it.
At this point I gave up on the report because there was no way for me to prove the vulnerability, and Facebook had no luck reproducing it. But…
September 23, 2015: Facebook informs me they have fixed the bug, and ask me to confirm it
September 24, 2015: After a lot of Googling I get my hands on a couple coupon codes, and try out the race condition. It is now fixed. A couple days later, Facebook closed the report:
I think this bug is not worth $7500, so I asked Facebook for an explanation of the bounty. Their reply:
Mega.nz coupons and purchasing race conditions
Mega was vulnerable to a coupons reuse race condition, very similar to one I found in DigitalOcean (writeup).
The other bug was present in the purchasing logic.
When you purchase Mega premium, a request is made to their API server eu.api.mega.co.nz/cs, which lowers balance and adds premium time. By sending multiple requests you could buy the premium multiple times, while your balance would go to negative values - this was not an intended functionality.
Mega rewarded me with a 250EUR bounty, which I told them to donate to LetsEncrypt.
Cheating Keybase invites system
First bug was present when generating invites for different emails. Let us assume you have 1 invite on your Keybase account. You could bypass the invitation limit by sending a bunch of POST requests with different email values to an API endpoint. Original report with the steps:
Couple months later I saw Keybase re-designed the system, and tried the same attack. It did not work, but a new bug was introduced to the registration flow, using which you could register multiple users while redeeming one invite. Original report:
Closing words and further reading
Here are some links if you want to read more about race conditions:
A writeup on an interesting CTF challenge, by @EdgarBoda of KITCTF team
Concurrency Attacks on Web Application, a video from BlueHat by @ScottStender and Alex Vidergar
A big thanks to all the companies listed for allowing me to write about those reports, and to you for reading!
Random blog post