06 Apr 2016
RubyGems.org gem replacement vulnerability and mitigation
RubyGems.org contained a bug that could allow an attacker to replace some .gem files on our servers with a different file that they supplied. We deployed a partial fix on April 2nd and a complete fix on April 4th, 2016. We also verified every .gem uploaded after Feb 8th, 2015, and found that none of them had been replaced. Gems whose name contains a dash (e.g. ‘blank-blank’) uploaded before that date should be verified by their authors. We’ve provided instructions on how to do that below.
On April 2nd, 2016 the RubyGems.org security team was made aware of a vulnerability that allowed an unauthorized user to update existing gem files for existing gem versions in certain circumstances. The security team evaluated the report and confirmed the bug that lead to this possibility. We deployed a fix later on April 2nd for this issue and confirmed that the exploit was no longer possible.
Upon further examination we discovered another similar attack vector not fixed with the original patch. We deployed a fix for this on April 4th and confirmed that this was also no longer possible.
In both attack vectors, an attacker could exploit the gem and version name combination to force the replacement of an existing .gem file in our S3 bucket.
We also found that a gem file pushed via this method would not be installable via the standard
gem install command.
Verification of existing gems
We verified the sha256 checksum in all the gems, and there were no gems that were maliciously changed. We only started calculating sha256 checksums on gem pushes Feb 8th, 2015. Gems pushed before that date didn’t have sha256 calculated at the push time. Therefore, if the gem was compromised before, we don’t have a way to verify it.
- Gems pushed after Feb 8th, 2015: 100% verified.
- Gems pushed before Feb 8th, 2015: Verified no changes since Feb 8th, 2015.
We also verified that there have been no cases of the second attack vector, for all gems, all dates.
As an extra verification step, we verified all the gems with two or more S3 object versions of the same file. We found a list of 750+ gems with multiple object versions in S3. We iterated over the multiple object versions and compared the last modification date on it against the creation of the entry on the DB. We found 6 gems out of that list that had a delta bigger than five seconds. Out of those six gems, we ran a checksum on the different versions, and only two gems had a different checksum. We manually ran a diff on the contents of those gems and ensured they were safe.
The first part of this security vulnerability was introduced on Jun 11, 2014.
The second part has been present since the beginning of RubyGems.org.
Gems with a dash in the name (for example, ‘blank-blank’) pushed between June 11th, 2014 and April 2nd, 2016 were vulnerable. (Gems pushed between Feb 8th, 2015 and April 2nd, 2016 have been verified already.)
What should I do?
If you have a gem version that matches the impact section:
- Download your gem
gem unpack file.gem
- Ensure there are no unexpected changes in it
gem spec file.gem
- Ensure there are no unexpected changes to the gemspec
If there are, please
gem yank the gem, and contact the RubyGems.org security team as soon as possible, and please include the .gem file for investigation.
Special thanks to Eric Chapweske for finding this and for his detailed report. David Radcliffe and Arthur Neves for working on the fixes and verifications. Aaron Patterson, Nick Quaranto, André Arko, and Samuel Giddins for reviewing and verifying.