When I first started analyzing the Coinbase website I had a quick look over the site layout and the functionality/attack surface available for potential exploitation. I quickly determined it was running Ruby on Rails based on the encoding of the “_coinbase_session” cookie. This was supported by the fact Coinbase’s founder Brian Armstrong had a lot of Ruby snippets on his Github Gist and some more Ruby questions on his Stack Overflow account.
1. Reflected XSS.
Previously I have had some successes finding XSS vulnerabilities in Flash .swf files on some sites. I quickly saw references to a file, https://coinbase.com/flash/ZeroClipboard.swf in the main CSS file. I recalled reading an advisory about this swf file before, but on first tests it did not appear to be exploitable. This .swf file is typically bundled with ZeroClipboard10.swf. In this case it was also uploaded but not referenced. Bingo! We have found a reflected XSS vulnerability on Coinbase with a known vulnerability in third party code (CVE-2013-1808).
I reported the vulnerability to Coinbase but @Ciaranmak, who referred me to the Coinbase bug bounty program had reported it independently a few hours before. The Coinbase team still sent me 1 BTC for it.
2. Persistent XSS on Merchant Checkout Pages.
I reported this issue to the Coinbase team and they had it fixed in a couple of hours.
3. Insecure OAuth Application Approval
After giving the site a look over for XSS/injection vulnerabilities I moved on to look at what else on the site was open for exploitation. Coinbase presents a standard REST API for their system which allows developers to interact with user accounts. The API allows users to authenticate to their own account with an API key, or use OAuth2 to grant authorization for a 3rd party app to interact with their Coinbase account. Egor Homakov has posted some interesting attacks against common implementations of the OAuth2 protocol on his blog. One of his posts, “The Most Common OAuth2 Vulnerability” gave me some ideas of what to look for.
It turns out that when a user is directed to Coinbase to authorize an application to access their account, Coinbase generates a token which is submitted along with the request when the user clicks the authorize button. Unfortunately they weren’t confirming that the token was valid for that user. As a result a attack could be performed a user is forced to submit an authorization requests generated for the attacker in the context of their own account, giving the attacker’s Coinbase OAuth application complete control of their account and transactions.
Here is a video of the Proof-of-Concept I created to demonstrate just how serious and transparent this attack was. A logged in Coinbase user who viewed a malicious page would give complete API access to their account to the attacker. Not only could the attacker withdraw all their Bitcoin balance, if the victim had a bank account linked to their Coinbase account the attacker could use their bank balance to buy more bitcoins and steal those too, completely oblivious to the user!
The source code for this proof of concept is available on my GitHub account.
Insecure OAuth Redirect URI in the Coinbase Mobile App
After finding that OAuth bug I was interested to find some more information about their backend systems and components to try and exploit it some more. I googled some of the error messages returned by the OAuth2 implementation such as “Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method” and it was clear they were using the Ruby based DoorKeeper. This is confirmed, as the Coinbase co-founder, Fred Ehrsam has created an issue on the repo.
Helpfully we now have some source code deployed by Coinbase. I had a look at the default implementation of validation for redirect URL’s to determine if there are any vulnerabilities but the default implementation checks for complete matches. This rules out many of the third party open redirect OAuth security issues affecting Facebook which has been disclosed recently.
Coinbase OAuth authorization is mainly used for their own Android app. Their app is open source and the code is available on Github. Rather than using the standard redirect of “urn:ietf:wg:oauth:2.0:oob”, the developers had instead setup their app using a redirect URL of “http://example.com/coinbase-redirect” and catching requests with that URL prefix in the app before they were sent. The vulnerability is that if a Coinbase mobile app user views the OAuth authorization form in their browse the were automatically redirect, and they would broadcast their private OAuth token across the network in plaintext to an untrusted endpoint “example.com”, run by the IANA. Check out the fix commit to see where their mistake was.
This might not seem very exploitable but imagine that your are in a coffee shop and would like to pay with Bitcoin. Conveniently the coffee shop has free WiFi. At point-of-sale you are asked by the friendly cashier to scan a QR code containing the Bitcoin payment info. The QR code actually goes to the Coinbase app authorization page, but as you have already authorized the Coinbase android app it just forwards you right on to the redirect url at “http://example.com/coinbase-redirect”. It would be trivial for that wireless network to intercept the request to example.com contain the OAuth token and forward you to the actually payment page, where you pay for your coffee and leave satisfied. As the victim you would have almost no way of knowing a third party now has your access tokens and can now withdraw your balance at any time!
Here’s a video demonstrating the insecure redirect. The code is also on my Github.
Chaining Vulnerabilities Together like a Real Attacker
Attackers won’t just exploit one weakness in isolation, but instead chain them together to affect a more complete attack on your sites, systems and users. Coinbase had an issue a few months back where merchant email addresses were being disclosed as a hidden field on their checkout pages which were then indexed by Google. Coinbase have a post on their blog about this. An attacker subsequently scraped these pages and then used the email addresses as targets for a phishing email.
The XSS payloads could have be written to act in a self replicating manner, like the Samy worm, attempting to compromise the accounts of any customers or merchants who make payments to a compromised account. With merchants like OKCupid and Reddit using Coinbase for their bitcoin payments it is easy to see how a chained attack like this could affect a lot of Coinbase customers and be very profitable for the attackers.
I had a lot of fun in the few hours I spent looking at Coinbase while procrastinating from exam study. They have done a lot of things right in regards to CSP, HttpOnly session cookies and two-step authentication but are let down with the integration of third party components such as Doorkeeper and ZeroClipboard. It is difficult to get any reasonably complex site completely secure and even sites doing more than $15 million USD per month in Bitcoin transaction volume can have a number of critical issues which a blackbox attacker could discover. I would recommend for all web developers to check out the guides on the OWASP website which cover all the key areas where security problems can occur in web apps.
Quite a few people are listed on the Coinbase White Hat page. I’d be very interested in hearing from some of you to get an idea of what kind of vulnerabilities I missed to try and impove my testing methodology.
The Coinbase team have been very responsive and worked over the weekend to fix the OAuth account takeover vulnerability, having it patched a few hours after I disclosed it to them. I’d just like to thank them again for their very nice rewards and for running a great service which helps to develop the Bitcoin economy.