Ruby on Rails (often called Rails) is a web application framework written in Ruby that emphasizes convention over configuration and the principle of "don't repeat yourself" (DRY). It provides developers with a structured and efficient way to build database-backed web applications through pre-built patterns for rapid development.
This vulnerability allows remote attackers to execute arbitrary Ruby code by leveraging an application's unrestricted use of the render method.
Remote code execution flaws are among the Top 10 Open Web Application Security Project (OWASP) vulnerabilities. They are among the most potentially damaging of vulnerabilities because injected, remotely executed code:
- can access internal application objects/methods
- can often bypass security controls
- may persist across sessions
- can often pivot to gain OS-level access.
Details
Module Info
- Product: Ruby on Rails Framework
- Affected packages: actionpack
- GitHub repository:
https://github.com/rails/rails/tree/main/actionpack - Published package: The individual actionpack gem or the entire Rails Framework gem (which includes actionpack).
- Package manager: gem
Vulnerability Info
Applications that pass unverified user input to the `render` method in a controller or a view may be vulnerable to a code injection.
Impacted code will look like this:
class TestController < ApplicationController
def show
render params[:id]
end
end
An attacker could use the request parameters to coerce the above example
to execute arbitrary ruby code.
Steps To Reproduce
1. Install a version of Rails that contains this vulnerability, such as 4.2.5.0:
gem install rails -v 4.2.5.0
rails _4.2.5.0_ new vulnerable_app
cd vulnerable_app
bundle install
2. Open config/routes.rb and add a route that includes the word "controller" in the path:
Rails.application.routes.draw do
get 'test/controller/test', to: 'welcome#index'
end
3. Generate a simple controller to handle the route:
rails generate controller Welcome index
4. Start the server:
rails server
5. Trigger the exploit:
curl http://localhost:3000/test/controller/test
6. Observe the denial of service:
- The server will hang or crash due to an infinite loop in the routing system.
- CPU and memory usage will spike as Rails tries to resolve "controller" recursively.
- The server may output stack overflow errors or become unresponsive.
Addressing the Issue
A workaround to this issue is to not pass arbitrary user input to the `render` method. Instead, verify that data before passing it to the `render` method.For example, change this:
def show
render params[:id]
end
To this:
def show
render verify_id(params[:id])
end
private
def verify_id(id)
# add verification logic particular to your application here
end
Credits
- Tobias Kraze from makandra and joernchen of Phenoelit
Mitigation
Users of affected versions of Ruby on Rails should follow one of the following mitigations:
- Upgrade to a corrected version.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.