A couple days we launched the Security Bug Bounty Program. Around 20 different white-hat hackers have been pounding away. Over 40 issues were reported; however, most were non-issues, low-priority, or duplicates. But there were a few that we accepted and rewarded a bounty. Here we will discuss these issues.
Before I go into the list, I want to thank all the hackers out there (and many customers) who have reported various product and security issues. I can confidently say they have made Factor.io a far better product. Thank you!
Autocomplete settings on credit card form
The credit card password field in Factor.io doesn’t set the autocomplete attributes. The issue was reported that autocomplete should be turned off. However, the autocomplete recommendations on jQuery.payment actually say to keep them on except the CVC. We sided with the feedback of Stripe and made the change, but still rewarded the bounty for bringing this to our attention.
Replay of password reset token
When you use the “Password Reset” capability in Factor.io you are sent an email with a reset token. The problem with the token is that can work more than once. The proper implementation is for the token to be one-time-use-only and to have a expiration period as well. This issue is not yet fixed and we are investigating the fix now.
Brute force of password
This is actually a relatively low priority bug. Theoretically someone could brute force the users password. Realistically that is very difficult to do given the 500ish ms processing time of requests and limited number of supported concurrent connections. A random 8 character alphanumeric password would take more than a lifetime.
- Possible passwords: (26+26+10)^8 = 218,340,105,584,896
- Password attempt rate: 100 concurrent connections with 0.5 response time = 200 passwords/sec
- Seconds to find password: 218,340,105,584,896/200 = 1,091,700,527,924
- Years to find password: ~1441
While this would be very difficult to perform on Factor.io, especially since we are monitoring other metrics that would indicate such an attack, we believed that it was good practice to put in counter measures in place.
As such, we implemented locks on the account. After 4 bad attempts you are warned of being locked out, after the 5th the account is locked. It is automatically unlocked after an hour. It can also be unlocked via email.
Session replay (won’t fix)
Log on to Factor.io, copy your session cookies, log out of Factor.io, paste in your session cookies, and even though you are logged out you are able to get access back into the service. I wrote Why session-replay is a won’t fix bug explaining why we are not planning on fixing this issue. This was by far the most reported issue (had about 10 reports).
Circumvent credit card form
If you try to create a new premium organization in Factor.io you are asked to provide credit card information for that organization. We use Stripe to process the credit card which returns a token from the JS Stripe library which then is passed to the server-side form. Once passed in the server validates that token and upgrades the plan. However, in our case we had a bug. After the form was submitted without a valid credit card the form returned an error due to a bad credit card, but the organization was still created. This was a design failure on our part as some of the validation was placed in the controller in an incorrect sequence. That was just bad design and we placed that validation in the model.
Create a friendly looking website with a button the user wants to click. But over that website you have an iframe with Factor.io with full transparency. The attacker can force you to take actions on Factor.io without you knowing it. The fix is simple, use the x-frame-options in your HTTP headers to instruct the browser not to use the site in an iframe. We used Twitter’s Secure Headers gem to fix this.