Skip to content

Commit

Permalink
Merge pull request #1162 from presidentbeef/avoid_warning_about_shell…
Browse files Browse the repository at this point in the history
…escape

Avoid command injection warning when using Shellwords.escape
  • Loading branch information
presidentbeef committed Feb 18, 2018
2 parents eb771bd + 905e142 commit 4b26a64
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 3 deletions.
24 changes: 21 additions & 3 deletions lib/brakeman/checks/check_execute.rb
Expand Up @@ -17,6 +17,10 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
s(:call, s(:const, :Rails), :root),
s(:call, s(:const, :Rails), :env)]

SHELL_ESCAPES = [:escape, :shellescape, :join]

SHELLWORDS = s(:const, :Shellwords)

#Check models, controllers, and views for command injection.
def run_check
Brakeman.debug "Finding system calls using ``"
Expand Down Expand Up @@ -127,15 +131,17 @@ def process_backticks result
:confidence => confidence
end

# This method expects a :dstr or :evstr node
def dangerous? exp
exp.each_sexp do |e|
next if node_type? e, :lit, :str
next if SAFE_VALUES.include? e

if call? e and e.method == :to_s
e = e.target
end

next if node_type? e, :lit, :str
next if SAFE_VALUES.include? e
next if shell_escape? e

if node_type? e, :or, :evstr, :dstr
if res = dangerous?(e)
return res
Expand All @@ -161,4 +167,16 @@ def dangerous_interp? exp

false
end

def shell_escape? exp
return false unless call? exp

if exp.target == SHELLWORDS and SHELL_ESCAPES.include? exp.method
true
elsif exp.method == :shelljoin
true
else
false
end
end
end
11 changes: 11 additions & 0 deletions test/apps/rails5.2/lib/shell.rb
@@ -0,0 +1,11 @@
class ShellStuff
def initialize(one, two)
@one = Shellwords.shellescape(one)
@two = Shellwords.escape(two)
end

def run(ip)
ip = Shellwords.shellescape(ip)
`dig +short -x #{ip} @#{@one} -p #{@two}`
end
end
13 changes: 13 additions & 0 deletions test/tests/rails52.rb
Expand Up @@ -52,4 +52,17 @@ def test_command_injection_1
:code => s(:dxstr, "", s(:evstr, s(:ivar, :@blah))),
:user_input => s(:ivar, :@blah)
end

def test_command_injection_shellwords
assert_no_warning :type => :warning,
:warning_code => 14,
:fingerprint => "89b886281c6329f5c5f319932d98ea96527d50f1d188fde9fd85ff93130b7c50",
:warning_type => "Command Injection",
:line => 9,
:message => /^Possible\ command\ injection/,
:confidence => 1,
:relative_path => "lib/shell.rb",
:code => s(:dxstr, "dig +short -x ", s(:evstr, s(:call, s(:const, :Shellwords), :shellescape, s(:lvar, :ip))), s(:str, " @"), s(:evstr, s(:call, s(:const, :Shellwords), :shellescape, s(:lvar, :one))), s(:str, " -p "), s(:evstr, s(:call, s(:const, :Shellwords), :escape, s(:lvar, :two)))),
:user_input => s(:call, s(:const, :Shellwords), :shellescape, s(:lvar, :ip))
end
end

0 comments on commit 4b26a64

Please sign in to comment.