HIGH command injectionsinatra

Command Injection in Sinatra

How Command Injection Manifests in Sinatra

Command injection in Sinatra applications typically occurs when user-controlled input is passed directly to system commands without proper sanitization. Sinatra's lightweight nature and Ruby's powerful system interaction capabilities create specific attack vectors that developers must understand.

The most common pattern involves using Ruby's backtick operator, %x(), Kernel#system, or Open3 methods with parameters derived from HTTP requests. For example:

get '/run-command' do
command = params[:cmd]
output = `#{command}`
output
end

This code is vulnerable because an attacker can inject additional commands using shell operators. A request to /run-command?cmd=echo%20hello;rm%20-rf%20/ would execute both commands sequentially.

Another Sinatra-specific pattern involves file operations combined with command execution. Developers often use user input to construct file paths, then execute commands on those files:

post '/process-file' do
filename = params[:filename]
`convert #{filename} -resize 200x200 output.png`
'File processed'
end

Here, an attacker could provide a filename like image.png; rm -rf /, causing destructive commands to execute.

Environment variable manipulation presents another vector. Sinatra applications often read configuration from environment variables, which can be manipulated if the application executes commands based on these values:

get '/run-script' do
script_path = ENV['SCRIPT_PATH'] || 'default_script.sh'
`#{script_path}`
'Script executed'
end

If an attacker can influence SCRIPT_PATH, they can execute arbitrary commands.

Parameter injection through URL encoding is particularly effective against Sinatra apps. The framework's lenient parameter parsing can allow attackers to craft requests that bypass simple input validation:

get '/search' do
query = params[:q]
`grep -i "#{query}" /var/log/system.log`
'Search complete'
end

An attacker could use q=pattern%22%3B%20rm%20-rf%20%2F%22 to close the grep pattern and inject additional commands.

Sinatra-Specific Detection

Detecting command injection vulnerabilities in Sinatra applications requires understanding both the framework's conventions and common Ruby patterns. Static analysis tools can identify dangerous code patterns, but runtime scanning provides more comprehensive coverage.

Code review should focus on these Sinatra-specific patterns:

grep -r -n 'backticks' . --include='*.rb'
grep -r -n 'system(' . --include='*.rb'
grep -r -n '%x' . --include='*.rb'
grep -r -n 'Open3' . --include='*.rb'

Look for instances where these methods receive parameters from request objects:

grep -r -n 'params\[.*\]' . --include='*.rb'

Dynamic analysis through automated scanning is more effective for production detection. middleBrick's black-box scanning approach tests the actual runtime behavior of your Sinatra API endpoints without requiring source code access.

The scanner identifies command injection vulnerabilities by:

  • Testing parameter injection points with shell metacharacters
  • Analyzing response patterns that indicate command execution
  • Checking for timing differences that suggest command processing
  • Verifying if error messages reveal system command failures

middleBrick specifically tests Sinatra applications for these vulnerabilities by sending crafted payloads to all endpoints and analyzing the responses. The scanner's 12 security checks include input validation testing that directly targets command injection scenarios.

For development environments, you can integrate middleBrick scanning into your CI/CD pipeline using the GitHub Action. This ensures that any new command injection vulnerabilities introduced during development are caught before deployment:

name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run middleBrick Scan
run: middlebrick scan http://localhost:4567

The CLI tool provides similar functionality for local testing:

middlebrick scan http://localhost:4567/api/v1 --output json

Sinatra-Specific Remediation

Remediating command injection in Sinatra requires both immediate fixes and architectural changes to prevent future vulnerabilities. The most effective approach combines input validation, command sanitization, and avoiding shell execution entirely when possible.

First, replace dangerous shell execution patterns with safer alternatives. Instead of using backticks or system calls, use Ruby's Process.spawn with argument arrays:

get '/run-command' do
command = params[:cmd]
# Dangerous - vulnerable to injection
# output = `#{command}`

# Safe - uses argument array
output, status = Open3.capture2e(['/bin/echo'], command)
output
end

For file operations, validate and sanitize file paths before processing:

post '/process-file' do
filename = params[:filename]
safe_filename = File.basename(filename)
full_path = File.join('/var/allowed-directory', safe_filename)

# Verify the resolved path is within the allowed directory
if full_path.start_with?('/var/allowed-directory')
`convert #{full_path} -resize 200x200 output.png`
'File processed'
else
halt 400, 'Invalid file path'
end
end

Implement comprehensive input validation using Sinatra's before filters:

before do
if request.path_info.start_with?('/admin')
# Validate that parameters contain only expected characters
params.each do |key, value|
if key =~ /^(cmd|command|script)$/i
halt 400, 'Invalid parameter detected'
end
if value =~ /[;|&$`()<>]/
halt 400, 'Invalid characters in parameter'
end
end
end
end

For applications that must execute system commands, use whitelisting instead of blacklisting:

VALID_COMMANDS = %w[ls pwd whoami].freeze
get '/execute' do
command = params[:cmd]

if VALID_COMMANDS.include?(command)
output = `#{command}`
output
else
halt 403, 'Command not allowed'
end
end

Consider using dedicated libraries for specific tasks instead of shell commands. For image processing, use the MiniMagick or ImageScience gems rather than calling ImageMagick directly:

require 'mini_magick'
post '/process-image' do
image = MiniMagick::Image.read(params[:file][:tempfile])
image.resize '200x200'
image.write 'output.png'
'Image processed'
end

middleBrick's scanning can verify that these remediation efforts are effective by testing the endpoints with various injection payloads and confirming that no command execution is possible.

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

Frequently Asked Questions

How can I test my Sinatra application for command injection vulnerabilities?
Use middleBrick's black-box scanning by submitting your API endpoint URL. The scanner tests for command injection by sending payloads containing shell metacharacters and analyzing responses for signs of command execution. You can also integrate middleBrick into your CI/CD pipeline using the GitHub Action to automatically scan before deployment.
What's the difference between command injection and other injection attacks in Sinatra?
Command injection specifically targets the operating system shell and allows attackers to execute arbitrary system commands. This differs from SQL injection (targets databases), XSS (targets browsers), or template injection (targets rendering engines). Command injection is particularly dangerous because it can lead to complete system compromise, data exfiltration, or lateral movement within your network.