We recently began emailing 3,420 Coinbase customers to let them know that a bug on our signup page resulted in some registration details being stored in clear text in our internal web server logs. While we are confident that we’ve fixed the root cause and that the logged information was not improperly accessed, misused, or compromised, we are requiring those customers to change their passwords as a best-practice precaution.
Here’s what happened
Under a very specific and rare error condition, the registration form on our signup page wouldn’t load correctly, which meant that any attempt to create a new Coinbase account under those conditions would fail. Unfortunately, it also meant that the individual’s name, email address, and proposed password (and state of residence, if in the US) would be sent to our internal logs.
If the individual reloaded the page and then submitted the form for a successful registration, their registration information would (correctly) not be logged, and the password would be securely hashed. However, in the 3,420 instances referenced above, the user successfully registered using a password with a hash that matched the one previously logged.
Here’s how we responded
After we identified and fixed the bug, we traced back all the places where these logs might have ended up. We have an internal logging system hosted in AWS, as well as a small number of log analysis service providers. Access to all of these systems is tightly restricted and audited. A thorough review of access to these logging systems did not reveal any unauthorized access to this data. Additionally, we triggered a password reset for impacted customers, even though a password alone is not sufficient to access a Coinbase account — our device verification emails and mandatory 2FA mechanisms would both have been triggered and blocked any unauthorized login attempts.
The technical details
The HTML form itself was extremely basic, since we expected that the details would be filled in by React:
. This had two implications for default behavior:
- Because no “action” attribute was set, the official behavior defined in the W3C specification was “undefined”. In practice, however, some browsers will set “action” to the current URI and make a best effort to submit the form.
- Because the “method” was not set, per W3C specification the browser defaulted to GET, which meant that, all form variables were URL encoded and appended as a query string to submit data to the server, e.g in the pattern /signup?first_name=Alice&last_name=Smith&email=alice%40example.com&password=password
This query string then ended up in our logs. The fix itself was simple and straightforward: we changed the default form method to POST, as data submitted in the request body (instead of a query string) is not logged:
. We also searched the rest of our repository for any other forms with that problematic behavior, and did not identify any. We’re also in the process of implementing additional mechanisms to detect and prevent the inadvertent introduction of this sort of bug in the future.
We maintain incredibly high standards for securing the Coinbase platform, and any time we fall even slightly short of those standards, we mobilize a team to figure out what went wrong, and how we prevent it from happening again. We also believe in being transparent with our customers, which is why we’re sharing the results of our investigation today.
As a reminder, Coinbase also maintains an active bug bounty program on HackerOne, which has paid out over a quarter of a million dollars to date: https://hackerone.com/coinbase. While this particular bug was discovered internally, we welcome security researchers to submit reports any time they believe they may have uncovered a flaw in one of our systems.
Post Mortem: A closer look at a password storage issue affecting 3,420 customers was originally published in The Coinbase Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.
Powered by WPeMatico