Class: Brakeman::CheckRedirect

Inherits:
BaseCheck
  • Object
show all
Defined in:
lib/brakeman/checks/check_redirect.rb

Overview

Reports any calls to redirect_to which include parameters in the arguments.

For example:

redirect_to params.merge(:action => :elsewhere)

Constant Summary

Constant Summary

Constants inherited from BaseCheck

BaseCheck::CONFIDENCE

Constants included from Util

Util::ALL_PARAMETERS, Util::COOKIES, Util::PARAMETERS, Util::PATH_PARAMETERS, Util::QUERY_PARAMETERS, Util::REQUEST_PARAMETERS, Util::SESSION

Instance Attribute Summary

Attributes inherited from BaseCheck

#tracker, #warnings

Instance Method Summary (collapse)

Methods inherited from BaseCheck

#add_result, #initialize, #process_call, #process_cookies, #process_default, #process_params

Methods included from Util

#array?, #call?, #camelize, #cookies?, #false?, #hash?, #hash_insert, #hash_iterate, #integer?, #number?, #params?, #pluralize, #regexp?, #result?, #set_env_defaults, #sexp?, #string?, #symbol?, #true?, #underscore

Methods included from ProcessorHelper

#class_name, #process_module

Constructor Details

This class inherits a constructor from Brakeman::BaseCheck

Instance Method Details

- (Object) check_url_for(call)

url_for is only_path => true by default. This checks to see if it is set to false for some reason.



101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/brakeman/checks/check_redirect.rb', line 101

def check_url_for call
  call[3].each do |arg|
    if hash? arg
      hash_iterate(arg) do |k,v|
        if symbol? k and k[1] == :only_path and v.is_a? Sexp and v[0] == :false
          return false
        end
      end
    end
  end

  true
end

- (Boolean) include_user_input?(call)

Custom check for user input. First looks to see if the user input is being output directly. This is necessary because of tracker.options which can be used to enable/disable reporting output of method calls which use user input as arguments.

Returns:

  • (Boolean)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/brakeman/checks/check_redirect.rb', line 44

def include_user_input? call
  debug_info "Checking if call includes user input"

  if tracker.options[:ignore_redirect_to_model] and call? call[3][1] and 
    call[3][1][2] == :new and call[3][1][1]

    begin
      target = class_name call[3][1][1]
      if @tracker.models.include? target
        return false
      end
    rescue
    end
  end

  call[3].each do |arg|
    if call? arg 
      if ALL_PARAMETERS.include? arg or arg[2] == COOKIES 
        return :immediate
      elsif arg[2] == :url_for and include_user_input? arg
        return :immediate
        #Ignore helpers like some_model_url?
      elsif arg[2].to_s =~ /_(url|path)$/
        return false
      end
    elsif params? arg or cookies? arg
      return :immediate
    end
  end

  if tracker.options[:check_arguments]
    super
  else
    false
  end
end

- (Boolean) only_path?(call)

Checks redirect_to arguments for only_path => true which essentially nullifies the danger posed by redirecting with user input

Returns:

  • (Boolean)


83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/brakeman/checks/check_redirect.rb', line 83

def only_path? call
  call[3].each do |arg|
    if hash? arg
      hash_iterate(arg) do |k,v|
        if symbol? k and k[1] == :only_path and v.is_a? Sexp and v[0] == :true
          return true
        end
      end
    elsif call? arg and arg[2] == :url_for
      return check_url_for(arg)
    end
  end

  false
end

- (Object) process_result(result)



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/brakeman/checks/check_redirect.rb', line 19

def process_result result
  call = result[:call]

  method = call[2]

  if method == :redirect_to and not only_path?(call) and res = include_user_input?(call)
    if res == :immediate
      confidence = CONFIDENCE[:high]
    else
      confidence = CONFIDENCE[:low]
    end

    warn :result => result,
      :warning_type => "Redirect",
      :message => "Possible unprotected redirect",
      :line => call.line,
      :code => call,
      :confidence => confidence
  end
end

- (Object) run_check



11
12
13
14
15
16
17
# File 'lib/brakeman/checks/check_redirect.rb', line 11

def run_check
  debug_info "Finding calls to redirect_to()"

  @tracker.find_call(:target => false, :method => :redirect_to).each do |res|
    process_result res
  end
end