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
endThis 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'
endHere, 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'
endIf 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'
endAn 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:4567The CLI tool provides similar functionality for local testing:
middlebrick scan http://localhost:4567/api/v1 --output jsonSinatra-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
endFor 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
endImplement 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
endFor 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
endConsider 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'
endmiddleBrick'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 ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |