CRITICAL command injectionrails

Command Injection in Rails

How Command Injection Manifests in Rails

Command injection in Rails applications typically occurs when user-controlled input is passed to system commands without proper sanitization. Rails developers often use methods like system, exec, or backticks (`) to execute shell commands, creating injection points when input isn't validated.

The most common Rails-specific patterns include:

  • Shell command execution with user input: system("ls -la #{params[:path]}") allows attackers to inject additional commands via crafted path parameters
  • Backtick execution: `git clone #{repo_url}` where repo_url comes from user input
  • Kernel.exec usage: exec("rm -rf #{params[:directory]}") can be exploited with semicolon-separated commands
  • Open3 with string interpolation: Open3.capture3("grep '#{search_term}' #{file}") where search_term is user-controlled

A particularly dangerous Rails pattern involves using params directly in shell commands. For example:

class ReportsController < ApplicationController
def generate
cmd = "wkhtmltopdf --page-size A4 #{params[:url]} report.pdf"
system(cmd)
send_file 'report.pdf'
end
end

An attacker could exploit this by visiting /reports/generate?url=example.com%20%26%26%20rm%20-rf%20/%26%26, causing the server to execute wkhtmltopdf --page-size A4 example.com && rm -rf / && report.pdf.

Rails applications also face command injection through:

  • ActiveRecord's connection.execute when combined with system calls
  • Delayed job workers that execute shell commands from database-stored strings
  • Background job processors like Sidekiq or Resque that run user-provided commands
  • Asset pipeline compilation with user-controlled input in custom build scripts

The Rails ecosystem's flexibility with metaprogramming and dynamic code execution creates additional attack surfaces. Methods like send, public_send, and method_missing can be combined with command execution in unexpected ways.

Rails-Specific Detection

Detecting command injection in Rails requires both static code analysis and runtime scanning. middleBrick's Rails-specific scanning identifies these vulnerabilities by analyzing your API endpoints and their parameters.

Static detection patterns middleBrick looks for:

# Dangerous patterns detected:
system(params[:input])
exec("command #{user_input}")
`echo #{unsafe_var}`
Kernel.system("ls #{path}")
Open3.capture3("grep '#{search}' #{file}")

middleBrick's Rails scanner specifically identifies:

  • Parameter-based command injection: Scanning for endpoints that accept parameters used in shell commands
  • Model attribute exploitation: Checking if database attributes containing user input are passed to system calls
  • Background job vulnerabilities: Analyzing job classes that execute shell commands with user data
  • Configuration file injection: Detecting if Rails configuration files allow command execution with user input

Runtime detection with middleBrick involves submitting your Rails API endpoints to the scanner. The tool tests for command injection by:

  1. Analyzing the OpenAPI/Swagger spec to understand parameter structures
  2. Crafting payloads that attempt to break out of the intended command context
  3. Monitoring system responses for signs of successful injection
  4. Testing across all 12 security categories, including input validation bypass attempts

For Rails applications, middleBrick provides specific findings like:

[CRITICAL] Command Injection - ReportsController#generate
Endpoint: POST /api/reports
Severity: Critical
Risk: System compromise possible
Remediation: Use Kernel.system with array syntax, validate input
Evidence: User input 'path' used in shell command without sanitization

The scanner also checks for Rails-specific command execution patterns in background jobs, rake tasks, and initializer files that might not be exposed through standard API endpoints.

Rails-Specific Remediation

Remediating command injection in Rails applications requires a multi-layered approach. The primary defense is eliminating shell command execution entirely when possible, but Rails provides several safe alternatives when system calls are necessary.

Safe command execution patterns:

# ✅ Safe - array syntax prevents shell interpretation
system(['ls', '-la', safe_path])

# ✅ Safe - Open3 with array syntax
Open3.capture3(['grep', safe_search, file_path])

# ✅ Safe - Process.spawn with arguments
Process.spawn('convert', image_path, '-resize', '200x200', output_path)

Input validation and sanitization:

class ReportsController < ApplicationController
VALID_PATHS = %w[reports uploads temp].freeze

def generate
path = params[:path].to_s
sanitized_path = sanitize_path(path)

unless VALID_PATHS.include?(sanitized_path)
render json: {error: 'Invalid path'}, status: :bad_request
return
end

cmd = ['wkhtmltopdf', '--page-size', 'A4', sanitized_path, 'report.pdf']
system(cmd)
send_file 'report.pdf'
end

private

def sanitize_path(path)
path.gsub(/[^a-zA-Z0-9_/\-]/, '') # Remove dangerous characters
end
end

Rails-specific security gems and practices:

  • Shellshocked: Provides shell command sanitization utilities
  • Brakeman: Static analysis tool that detects command injection patterns
  • Danger: CI tool that can flag command injection in code reviews

Background job security:

class SecureJob < ApplicationJob
def perform(user_input)

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL