Insecure Use of Dangerous Function

This vulnerability category covers the following issues:

Command Injection

Why is this important?

Ruby, like any other programming language, has dangerous functions. If these functions are not used properly, it can have a catastrophic impact on your app. Ruby offers several ways to execute operating system commands, such as:

  • exec(command)
  • syscall(command)
  • system(command)
  • eval()
  • constantize()
  • render()

Attacker controlled input, that is processed by any of these functions, can lead to attackers getting full access to your production environment.

Check out this video for a high-level explanation:

OS Command Injection

Read below to find out how to fix this issue in your code.

Fixing Insecure Use of Dangerous Function

Option A: Replace the dangerous function with a secure alternative

  1. Go through the issues that GuardRails identified in the PR.
  2. Locate the dangerous function. For example:

    # One example is exec, but many other dangerous functions exist in Ruby.
    exec("/path/to/cmd #{params[:input]}")
    
  3. If the functionality is not required, then remove it.

  4. Otherwise, replace the dangerous function with the following:

    # The key point is that the user input is in the second part of the Array
    # that is passed to the system function.
    # Make sure that no user input is in the first part of the Array that
    # contains the command itself.
    system("/path/to/cmd","#{params[:input]}")
    
  5. Test it and ensure the functionality works as expected

  6. Ship it 🚢 and relax 🌴

Option B: Using constantize safely

  1. Go through the issues that GuardRails identified in the PR.
  2. Locate the constantize method. A vulnerable example is:

     class AlertsController < ApplicationController
       def create
         params[:alert][:type].constantize.new(params[:alert][:value])  # <-- bad code don't do this!
         # ... other work
         # render page
       end
     end
    
  3. If the functionality is not required, then remove it.

  4. Otherwise, apply the following pattern:

     # Some file where a constant definition is appropriate.
     ALERTS = {
       'info' => InfoAlert,
       'warn' => WarnAlert,
       'error' => ErrorAlert
     }
    
     class AlertsController < ApplicationController
       def create
         ALERTS.fetch(params[:alert][:type])).new(params[:alert][:value]))
    
         # ... other work
         # render page
       end
     end
    
  5. Test it and ensure the functionality works as expected

  6. Ship it 🚢 and relax 🌴

Option C: Restrict Allowed Input to Render()

  1. Go through the issues that GuardRails identified in the PR.
  2. Locate the render method. A vulnerable example is:

     def show
       render params[:template]
     end
    
  3. Apply the following pattern:

     def show
       template = params[:id]
    
       valid_templates = {
         "dashboard" => "dashboard",
         "profile"   => "profile",
         "deals"   => "deals"
       }
    
       if valid_templates.include?(template)
         render " #{valid_templates[template]}"
       else
         # throw exception or 404
       end
     end
    
  4. Test it and ensure the functionality works as expected

  5. Ship it 🚢 and relax 🌴

More information: