brakeman-lib 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +872 -0
  3. data/FEATURES +16 -0
  4. data/README.md +169 -0
  5. data/WARNING_TYPES +95 -0
  6. data/bin/brakeman +89 -0
  7. data/lib/brakeman.rb +495 -0
  8. data/lib/brakeman/app_tree.rb +161 -0
  9. data/lib/brakeman/brakeman.rake +17 -0
  10. data/lib/brakeman/call_index.rb +219 -0
  11. data/lib/brakeman/checks.rb +191 -0
  12. data/lib/brakeman/checks/base_check.rb +518 -0
  13. data/lib/brakeman/checks/check_basic_auth.rb +88 -0
  14. data/lib/brakeman/checks/check_basic_auth_timing_attack.rb +33 -0
  15. data/lib/brakeman/checks/check_content_tag.rb +160 -0
  16. data/lib/brakeman/checks/check_create_with.rb +75 -0
  17. data/lib/brakeman/checks/check_cross_site_scripting.rb +385 -0
  18. data/lib/brakeman/checks/check_default_routes.rb +86 -0
  19. data/lib/brakeman/checks/check_deserialize.rb +57 -0
  20. data/lib/brakeman/checks/check_detailed_exceptions.rb +55 -0
  21. data/lib/brakeman/checks/check_digest_dos.rb +38 -0
  22. data/lib/brakeman/checks/check_dynamic_finders.rb +49 -0
  23. data/lib/brakeman/checks/check_escape_function.rb +21 -0
  24. data/lib/brakeman/checks/check_evaluation.rb +36 -0
  25. data/lib/brakeman/checks/check_execute.rb +167 -0
  26. data/lib/brakeman/checks/check_file_access.rb +63 -0
  27. data/lib/brakeman/checks/check_file_disclosure.rb +35 -0
  28. data/lib/brakeman/checks/check_filter_skipping.rb +31 -0
  29. data/lib/brakeman/checks/check_forgery_setting.rb +74 -0
  30. data/lib/brakeman/checks/check_header_dos.rb +31 -0
  31. data/lib/brakeman/checks/check_i18n_xss.rb +48 -0
  32. data/lib/brakeman/checks/check_jruby_xml.rb +38 -0
  33. data/lib/brakeman/checks/check_json_encoding.rb +47 -0
  34. data/lib/brakeman/checks/check_json_parsing.rb +107 -0
  35. data/lib/brakeman/checks/check_link_to.rb +132 -0
  36. data/lib/brakeman/checks/check_link_to_href.rb +115 -0
  37. data/lib/brakeman/checks/check_mail_to.rb +49 -0
  38. data/lib/brakeman/checks/check_mass_assignment.rb +198 -0
  39. data/lib/brakeman/checks/check_mime_type_dos.rb +39 -0
  40. data/lib/brakeman/checks/check_model_attr_accessible.rb +55 -0
  41. data/lib/brakeman/checks/check_model_attributes.rb +119 -0
  42. data/lib/brakeman/checks/check_model_serialize.rb +67 -0
  43. data/lib/brakeman/checks/check_nested_attributes.rb +38 -0
  44. data/lib/brakeman/checks/check_nested_attributes_bypass.rb +58 -0
  45. data/lib/brakeman/checks/check_number_to_currency.rb +74 -0
  46. data/lib/brakeman/checks/check_quote_table_name.rb +40 -0
  47. data/lib/brakeman/checks/check_redirect.rb +215 -0
  48. data/lib/brakeman/checks/check_regex_dos.rb +69 -0
  49. data/lib/brakeman/checks/check_render.rb +92 -0
  50. data/lib/brakeman/checks/check_render_dos.rb +37 -0
  51. data/lib/brakeman/checks/check_render_inline.rb +54 -0
  52. data/lib/brakeman/checks/check_response_splitting.rb +21 -0
  53. data/lib/brakeman/checks/check_route_dos.rb +42 -0
  54. data/lib/brakeman/checks/check_safe_buffer_manipulation.rb +31 -0
  55. data/lib/brakeman/checks/check_sanitize_methods.rb +79 -0
  56. data/lib/brakeman/checks/check_secrets.rb +40 -0
  57. data/lib/brakeman/checks/check_select_tag.rb +60 -0
  58. data/lib/brakeman/checks/check_select_vulnerability.rb +60 -0
  59. data/lib/brakeman/checks/check_send.rb +48 -0
  60. data/lib/brakeman/checks/check_send_file.rb +19 -0
  61. data/lib/brakeman/checks/check_session_manipulation.rb +36 -0
  62. data/lib/brakeman/checks/check_session_settings.rb +170 -0
  63. data/lib/brakeman/checks/check_simple_format.rb +59 -0
  64. data/lib/brakeman/checks/check_single_quotes.rb +101 -0
  65. data/lib/brakeman/checks/check_skip_before_filter.rb +60 -0
  66. data/lib/brakeman/checks/check_sql.rb +660 -0
  67. data/lib/brakeman/checks/check_sql_cves.rb +101 -0
  68. data/lib/brakeman/checks/check_ssl_verify.rb +49 -0
  69. data/lib/brakeman/checks/check_strip_tags.rb +89 -0
  70. data/lib/brakeman/checks/check_symbol_dos.rb +64 -0
  71. data/lib/brakeman/checks/check_symbol_dos_cve.rb +30 -0
  72. data/lib/brakeman/checks/check_translate_bug.rb +45 -0
  73. data/lib/brakeman/checks/check_unsafe_reflection.rb +51 -0
  74. data/lib/brakeman/checks/check_unscoped_find.rb +41 -0
  75. data/lib/brakeman/checks/check_validation_regex.rb +116 -0
  76. data/lib/brakeman/checks/check_weak_hash.rb +151 -0
  77. data/lib/brakeman/checks/check_without_protection.rb +80 -0
  78. data/lib/brakeman/checks/check_xml_dos.rb +51 -0
  79. data/lib/brakeman/checks/check_yaml_parsing.rb +121 -0
  80. data/lib/brakeman/differ.rb +66 -0
  81. data/lib/brakeman/file_parser.rb +50 -0
  82. data/lib/brakeman/format/style.css +133 -0
  83. data/lib/brakeman/options.rb +301 -0
  84. data/lib/brakeman/parsers/rails2_erubis.rb +6 -0
  85. data/lib/brakeman/parsers/rails2_xss_plugin_erubis.rb +48 -0
  86. data/lib/brakeman/parsers/rails3_erubis.rb +74 -0
  87. data/lib/brakeman/parsers/template_parser.rb +89 -0
  88. data/lib/brakeman/processor.rb +102 -0
  89. data/lib/brakeman/processors/alias_processor.rb +1013 -0
  90. data/lib/brakeman/processors/base_processor.rb +277 -0
  91. data/lib/brakeman/processors/config_processor.rb +14 -0
  92. data/lib/brakeman/processors/controller_alias_processor.rb +273 -0
  93. data/lib/brakeman/processors/controller_processor.rb +326 -0
  94. data/lib/brakeman/processors/erb_template_processor.rb +80 -0
  95. data/lib/brakeman/processors/erubis_template_processor.rb +104 -0
  96. data/lib/brakeman/processors/gem_processor.rb +57 -0
  97. data/lib/brakeman/processors/haml_template_processor.rb +190 -0
  98. data/lib/brakeman/processors/lib/basic_processor.rb +37 -0
  99. data/lib/brakeman/processors/lib/find_all_calls.rb +223 -0
  100. data/lib/brakeman/processors/lib/find_call.rb +183 -0
  101. data/lib/brakeman/processors/lib/find_return_value.rb +134 -0
  102. data/lib/brakeman/processors/lib/processor_helper.rb +75 -0
  103. data/lib/brakeman/processors/lib/rails2_config_processor.rb +145 -0
  104. data/lib/brakeman/processors/lib/rails2_route_processor.rb +313 -0
  105. data/lib/brakeman/processors/lib/rails3_config_processor.rb +132 -0
  106. data/lib/brakeman/processors/lib/rails3_route_processor.rb +308 -0
  107. data/lib/brakeman/processors/lib/render_helper.rb +181 -0
  108. data/lib/brakeman/processors/lib/render_path.rb +107 -0
  109. data/lib/brakeman/processors/lib/route_helper.rb +68 -0
  110. data/lib/brakeman/processors/lib/safe_call_helper.rb +16 -0
  111. data/lib/brakeman/processors/library_processor.rb +119 -0
  112. data/lib/brakeman/processors/model_processor.rb +191 -0
  113. data/lib/brakeman/processors/output_processor.rb +171 -0
  114. data/lib/brakeman/processors/route_processor.rb +17 -0
  115. data/lib/brakeman/processors/slim_template_processor.rb +107 -0
  116. data/lib/brakeman/processors/template_alias_processor.rb +116 -0
  117. data/lib/brakeman/processors/template_processor.rb +74 -0
  118. data/lib/brakeman/report.rb +78 -0
  119. data/lib/brakeman/report/config/remediation.yml +71 -0
  120. data/lib/brakeman/report/ignore/config.rb +135 -0
  121. data/lib/brakeman/report/ignore/interactive.rb +311 -0
  122. data/lib/brakeman/report/renderer.rb +24 -0
  123. data/lib/brakeman/report/report_base.rb +286 -0
  124. data/lib/brakeman/report/report_codeclimate.rb +70 -0
  125. data/lib/brakeman/report/report_csv.rb +55 -0
  126. data/lib/brakeman/report/report_hash.rb +23 -0
  127. data/lib/brakeman/report/report_html.rb +216 -0
  128. data/lib/brakeman/report/report_json.rb +42 -0
  129. data/lib/brakeman/report/report_markdown.rb +156 -0
  130. data/lib/brakeman/report/report_table.rb +107 -0
  131. data/lib/brakeman/report/report_tabs.rb +17 -0
  132. data/lib/brakeman/report/templates/controller_overview.html.erb +22 -0
  133. data/lib/brakeman/report/templates/controller_warnings.html.erb +21 -0
  134. data/lib/brakeman/report/templates/error_overview.html.erb +29 -0
  135. data/lib/brakeman/report/templates/header.html.erb +58 -0
  136. data/lib/brakeman/report/templates/ignored_warnings.html.erb +25 -0
  137. data/lib/brakeman/report/templates/model_warnings.html.erb +21 -0
  138. data/lib/brakeman/report/templates/overview.html.erb +38 -0
  139. data/lib/brakeman/report/templates/security_warnings.html.erb +23 -0
  140. data/lib/brakeman/report/templates/template_overview.html.erb +21 -0
  141. data/lib/brakeman/report/templates/view_warnings.html.erb +34 -0
  142. data/lib/brakeman/report/templates/warning_overview.html.erb +17 -0
  143. data/lib/brakeman/rescanner.rb +483 -0
  144. data/lib/brakeman/scanner.rb +317 -0
  145. data/lib/brakeman/tracker.rb +347 -0
  146. data/lib/brakeman/tracker/collection.rb +93 -0
  147. data/lib/brakeman/tracker/config.rb +101 -0
  148. data/lib/brakeman/tracker/constants.rb +101 -0
  149. data/lib/brakeman/tracker/controller.rb +161 -0
  150. data/lib/brakeman/tracker/library.rb +17 -0
  151. data/lib/brakeman/tracker/model.rb +90 -0
  152. data/lib/brakeman/tracker/template.rb +33 -0
  153. data/lib/brakeman/util.rb +481 -0
  154. data/lib/brakeman/version.rb +3 -0
  155. data/lib/brakeman/warning.rb +255 -0
  156. data/lib/brakeman/warning_codes.rb +111 -0
  157. data/lib/ruby_parser/bm_sexp.rb +610 -0
  158. data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
  159. metadata +362 -0
@@ -0,0 +1,40 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ #Check for uses of quote_table_name in Rails versions before 2.3.13 and 3.0.10
4
+ #http://groups.google.com/group/rubyonrails-security/browse_thread/thread/6a1e473744bc389b
5
+ class Brakeman::CheckQuoteTableName < Brakeman::BaseCheck
6
+ Brakeman::Checks.add self
7
+
8
+ @description = "Checks for quote_table_name vulnerability in versions before 2.3.14 and 3.0.10"
9
+
10
+ def run_check
11
+ if (version_between?('2.0.0', '2.3.13') or
12
+ version_between?('3.0.0', '3.0.9'))
13
+
14
+ if uses_quote_table_name?
15
+ confidence = CONFIDENCE[:high]
16
+ else
17
+ confidence = CONFIDENCE[:med]
18
+ end
19
+
20
+ if rails_version =~ /^3/
21
+ message = "Versions before 3.0.10 have a vulnerability in quote_table_name: CVE-2011-2930"
22
+ else
23
+ message = "Versions before 2.3.14 have a vulnerability in quote_table_name: CVE-2011-2930"
24
+ end
25
+
26
+ warn :warning_type => "SQL Injection",
27
+ :warning_code => :CVE_2011_2930,
28
+ :message => message,
29
+ :confidence => confidence,
30
+ :gem_info => gemfile_or_environment,
31
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/ah5HN0S8OJs/discussion"
32
+ end
33
+ end
34
+
35
+ def uses_quote_table_name?
36
+ Brakeman.debug "Finding calls to quote_table_name()"
37
+
38
+ not tracker.find_call(:target => false, :method => :quote_table_name).empty?
39
+ end
40
+ end
@@ -0,0 +1,215 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ #Reports any calls to +redirect_to+ which include parameters in the arguments.
4
+ #
5
+ #For example:
6
+ #
7
+ # redirect_to params.merge(:action => :elsewhere)
8
+ class Brakeman::CheckRedirect < Brakeman::BaseCheck
9
+ Brakeman::Checks.add self
10
+
11
+ @description = "Looks for calls to redirect_to with user input as arguments"
12
+
13
+ def run_check
14
+ Brakeman.debug "Finding calls to redirect_to()"
15
+
16
+ @model_find_calls = Set[:all, :create, :create!, :find, :find_by_sql, :first, :last, :new]
17
+
18
+ if tracker.options[:rails3]
19
+ @model_find_calls.merge [:from, :group, :having, :joins, :lock, :order, :reorder, :select, :where]
20
+ end
21
+
22
+ if version_between? "4.0.0", "9.9.9"
23
+ @model_find_calls.merge [:find_by, :find_by!, :take]
24
+ end
25
+
26
+ @tracker.find_call(:target => false, :method => :redirect_to).each do |res|
27
+ process_result res
28
+ end
29
+ end
30
+
31
+ def process_result result
32
+ return if duplicate? result
33
+
34
+ call = result[:call]
35
+
36
+ method = call.method
37
+
38
+ if method == :redirect_to and
39
+ not only_path?(call) and
40
+ not explicit_host?(call.first_arg) and
41
+ not slice_call?(call.first_arg) and
42
+ res = include_user_input?(call)
43
+
44
+ add_result result
45
+
46
+ if res.type == :immediate
47
+ confidence = CONFIDENCE[:high]
48
+ else
49
+ confidence = CONFIDENCE[:low]
50
+ end
51
+
52
+ warn :result => result,
53
+ :warning_type => "Redirect",
54
+ :warning_code => :open_redirect,
55
+ :message => "Possible unprotected redirect",
56
+ :code => call,
57
+ :user_input => res,
58
+ :confidence => confidence
59
+ end
60
+ end
61
+
62
+ #Custom check for user input. First looks to see if the user input
63
+ #is being output directly. This is necessary because of tracker.options[:check_arguments]
64
+ #which can be used to enable/disable reporting output of method calls which use
65
+ #user input as arguments.
66
+ def include_user_input? call, immediate = :immediate
67
+ Brakeman.debug "Checking if call includes user input"
68
+
69
+ arg = call.first_arg
70
+
71
+ # if the first argument is an array, rails assumes you are building a
72
+ # polymorphic route, which will never jump off-host
73
+ return false if array? arg
74
+
75
+ if tracker.options[:ignore_redirect_to_model]
76
+ if model_instance?(arg) or decorated_model?(arg)
77
+ return false
78
+ end
79
+ end
80
+
81
+ if res = has_immediate_model?(arg)
82
+ return Match.new(immediate, res)
83
+ elsif call? arg
84
+ if request_value? arg
85
+ return Match.new(immediate, arg)
86
+ elsif request_value? arg.target
87
+ return Match.new(immediate, arg.target)
88
+ elsif arg.method == :url_for and include_user_input? arg
89
+ return Match.new(immediate, arg)
90
+ #Ignore helpers like some_model_url?
91
+ elsif arg.method.to_s =~ /_(url|path)\z/
92
+ return false
93
+ end
94
+ elsif request_value? arg
95
+ return Match.new(immediate, arg)
96
+ end
97
+
98
+ if tracker.options[:check_arguments] and call? arg
99
+ include_user_input? arg, false #I'm doubting if this is really necessary...
100
+ else
101
+ false
102
+ end
103
+ end
104
+
105
+ #Checks +redirect_to+ arguments for +only_path => true+ which essentially
106
+ #nullifies the danger posed by redirecting with user input
107
+ def only_path? call
108
+ arg = call.first_arg
109
+
110
+ if hash? arg
111
+ if value = hash_access(arg, :only_path)
112
+ return true if true?(value)
113
+ end
114
+ elsif call? arg and arg.method == :url_for
115
+ return check_url_for(arg)
116
+ end
117
+
118
+ false
119
+ end
120
+
121
+ def explicit_host? arg
122
+ return unless sexp? arg
123
+
124
+ if hash? arg
125
+ if value = hash_access(arg, :host)
126
+ return !has_immediate_user_input?(value)
127
+ end
128
+ elsif call? arg
129
+ target = arg.target
130
+
131
+ if hash? target and value = hash_access(target, :host)
132
+ return !has_immediate_user_input?(value)
133
+ elsif call? arg
134
+ return explicit_host? target
135
+ end
136
+ end
137
+
138
+ false
139
+ end
140
+
141
+ #+url_for+ is only_path => true by default. This checks to see if it is
142
+ #set to false for some reason.
143
+ def check_url_for call
144
+ arg = call.first_arg
145
+
146
+ if hash? arg
147
+ if value = hash_access(arg, :only_path)
148
+ return false if false?(value)
149
+ end
150
+ end
151
+
152
+ true
153
+ end
154
+
155
+ #Returns true if exp is (probably) a model instance
156
+ def model_instance? exp
157
+ if node_type? exp, :or
158
+ model_instance? exp.lhs or model_instance? exp.rhs
159
+ elsif call? exp
160
+ if model_target? exp and
161
+ (@model_find_calls.include? exp.method or exp.method.to_s.match(/^find_by_/))
162
+ true
163
+ else
164
+ association?(exp.target, exp.method)
165
+ end
166
+ end
167
+ end
168
+
169
+ def model_target? exp
170
+ return false unless call? exp
171
+ model_name? exp.target or
172
+ friendly_model? exp.target or
173
+ model_target? exp.target
174
+ end
175
+
176
+ #Returns true if exp is (probably) a friendly model instance
177
+ #using the FriendlyId gem
178
+ def friendly_model? exp
179
+ call? exp and model_name? exp.target and exp.method == :friendly
180
+ end
181
+
182
+ #Returns true if exp is (probably) a decorated model instance
183
+ #using the Draper gem
184
+ def decorated_model? exp
185
+ if node_type? exp, :or
186
+ decorated_model? exp.lhs or decorated_model? exp.rhs
187
+ else
188
+ tracker.config.has_gem? :draper and
189
+ call? exp and
190
+ node_type?(exp.target, :const) and
191
+ exp.target.value.to_s.match(/Decorator$/) and
192
+ exp.method == :decorate
193
+ end
194
+ end
195
+
196
+ #Check if method is actually an association in a Model
197
+ def association? model_name, meth
198
+ if call? model_name
199
+ return association? model_name.target, meth
200
+ elsif model_name? model_name
201
+ model = tracker.models[class_name(model_name)]
202
+ else
203
+ return false
204
+ end
205
+
206
+ return false unless model
207
+
208
+ model.association? meth
209
+ end
210
+
211
+ def slice_call? exp
212
+ return unless call? exp
213
+ exp.method == :slice
214
+ end
215
+ end
@@ -0,0 +1,69 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ #This check looks for regexes that include user input.
4
+ class Brakeman::CheckRegexDoS < Brakeman::BaseCheck
5
+ Brakeman::Checks.add self
6
+
7
+ ESCAPES = {
8
+ s(:const, :Regexp) => [
9
+ :escape,
10
+ :quote
11
+ ]
12
+ }
13
+
14
+ @description = "Searches regexes including user input"
15
+
16
+ #Process calls
17
+ def run_check
18
+ Brakeman.debug "Finding dynamic regexes"
19
+ calls = tracker.find_call :method => [:brakeman_regex_interp]
20
+
21
+ Brakeman.debug "Processing dynamic regexes"
22
+ calls.each do |call|
23
+ process_result call
24
+ end
25
+ end
26
+
27
+ #Warns if regex includes user input
28
+ def process_result result
29
+ return if duplicate? result or result[:call].original_line
30
+ add_result result
31
+
32
+ call = result[:call]
33
+ components = call[1..-1]
34
+
35
+ components.any? do |component|
36
+ next unless sexp? component
37
+
38
+ if match = has_immediate_user_input?(component)
39
+ confidence = CONFIDENCE[:high]
40
+ elsif match = has_immediate_model?(component)
41
+ match = Match.new(:model, match)
42
+ confidence = CONFIDENCE[:med]
43
+ elsif match = include_user_input?(component)
44
+ confidence = CONFIDENCE[:low]
45
+ end
46
+
47
+ if match
48
+ message = "#{friendly_type_of(match).capitalize} used in regex"
49
+
50
+ warn :result => result,
51
+ :warning_type => "Denial of Service",
52
+ :warning_code => :regex_dos,
53
+ :message => message,
54
+ :confidence => confidence,
55
+ :user_input => match
56
+ end
57
+ end
58
+ end
59
+
60
+ def process_call(exp)
61
+ if escape_methods = ESCAPES[exp.target]
62
+ if escape_methods.include? exp.method
63
+ return exp
64
+ end
65
+ end
66
+
67
+ super
68
+ end
69
+ end
@@ -0,0 +1,92 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ #Check calls to +render()+ for dangerous values
4
+ class Brakeman::CheckRender < Brakeman::BaseCheck
5
+ Brakeman::Checks.add self
6
+
7
+ @description = "Finds calls to render that might allow file access or code execution"
8
+
9
+ def run_check
10
+ tracker.find_call(:target => nil, :method => :render).each do |result|
11
+ process_render_result result
12
+ end
13
+ end
14
+
15
+ def process_render_result result
16
+ return unless node_type? result[:call], :render
17
+
18
+ case result[:call].render_type
19
+ when :partial, :template, :action, :file
20
+ check_for_rce(result) or
21
+ check_for_dynamic_path(result)
22
+ when :inline
23
+ when :js
24
+ when :json
25
+ when :text
26
+ when :update
27
+ when :xml
28
+ end
29
+ end
30
+
31
+ #Check if path to action or file is determined dynamically
32
+ def check_for_dynamic_path result
33
+ view = result[:call][2]
34
+
35
+ if sexp? view and not duplicate? result
36
+ add_result result
37
+
38
+ if input = has_immediate_user_input?(view)
39
+ if string_interp? view
40
+ confidence = CONFIDENCE[:med]
41
+ else
42
+ confidence = CONFIDENCE[:high]
43
+ end
44
+ elsif input = include_user_input?(view)
45
+ confidence = CONFIDENCE[:low]
46
+ else
47
+ return
48
+ end
49
+
50
+ return if input.type == :model #skip models
51
+ return if safe_param? input.match
52
+
53
+ message = "Render path contains #{friendly_type_of input}"
54
+
55
+ warn :result => result,
56
+ :warning_type => "Dynamic Render Path",
57
+ :warning_code => :dynamic_render_path,
58
+ :message => message,
59
+ :user_input => input,
60
+ :confidence => confidence
61
+ end
62
+ end
63
+
64
+ def check_for_rce result
65
+ return unless version_between? "0.0.0", "3.2.22" or
66
+ version_between? "4.0.0", "4.1.14" or
67
+ version_between? "4.2.0", "4.2.5"
68
+
69
+
70
+ view = result[:call][2]
71
+ if sexp? view and not duplicate? result
72
+ if params? view
73
+ add_result result
74
+ return if safe_param? view
75
+
76
+ warn :result => result,
77
+ :warning_type => "Remote Code Execution",
78
+ :warning_code => :dynamic_render_path_rce,
79
+ :message => "Passing query parameters to render() is vulnerable in Rails #{rails_version} (CVE-2016-0752)",
80
+ :user_input => view,
81
+ :confidence => CONFIDENCE[:high]
82
+ end
83
+ end
84
+ end
85
+
86
+ def safe_param? exp
87
+ if params? exp and call? exp and exp.method == :[]
88
+ arg = exp.first_arg
89
+ symbol? arg and [:controller, :action].include? arg.value
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,37 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckRenderDoS < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Warn about denial of service with render :text (CVE-2014-0082)"
7
+
8
+ def run_check
9
+ if version_between? "3.0.0", "3.0.20" or
10
+ version_between? "3.1.0", "3.1.12" or
11
+ version_between? "3.2.0", "3.2.16"
12
+
13
+ tracker.find_call(:target => nil, :method => :render).each do |result|
14
+ if text_render? result
15
+ warn_about_text_render
16
+ break
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def text_render? result
23
+ node_type? result[:call], :render and
24
+ result[:call].render_type == :text
25
+ end
26
+
27
+ def warn_about_text_render
28
+ message = "Rails #{rails_version} has a denial of service vulnerability (CVE-2014-0082). Upgrade to Rails version 3.2.17"
29
+
30
+ warn :warning_type => "Denial of Service",
31
+ :warning_code => :CVE_2014_0082,
32
+ :message => message,
33
+ :confidence => CONFIDENCE[:high],
34
+ :link_path => "https://groups.google.com/d/msg/rubyonrails-security/LMxO_3_eCuc/ozGBEhKaJbIJ",
35
+ :gem_info => gemfile_or_environment
36
+ end
37
+ end