brakeman 3.0.5 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES +19 -0
- data/README.md +3 -13
- data/lib/brakeman.rb +3 -0
- data/lib/brakeman/checks/base_check.rb +19 -47
- data/lib/brakeman/checks/check_basic_auth.rb +3 -3
- data/lib/brakeman/checks/check_cross_site_scripting.rb +26 -12
- data/lib/brakeman/checks/check_default_routes.rb +1 -1
- data/lib/brakeman/checks/check_detailed_exceptions.rb +2 -2
- data/lib/brakeman/checks/check_evaluation.rb +3 -0
- data/lib/brakeman/checks/check_execute.rb +3 -3
- data/lib/brakeman/checks/check_file_disclosure.rb +2 -2
- data/lib/brakeman/checks/check_forgery_setting.rb +9 -12
- data/lib/brakeman/checks/check_header_dos.rb +1 -1
- data/lib/brakeman/checks/check_i18n_xss.rb +2 -2
- data/lib/brakeman/checks/check_jruby_xml.rb +1 -1
- data/lib/brakeman/checks/check_json_encoding.rb +1 -1
- data/lib/brakeman/checks/check_json_parsing.rb +3 -3
- data/lib/brakeman/checks/check_link_to.rb +1 -1
- data/lib/brakeman/checks/check_link_to_href.rb +9 -2
- data/lib/brakeman/checks/check_mass_assignment.rb +5 -2
- data/lib/brakeman/checks/check_model_attr_accessible.rb +4 -4
- data/lib/brakeman/checks/check_model_attributes.rb +7 -7
- data/lib/brakeman/checks/check_model_serialize.rb +6 -6
- data/lib/brakeman/checks/check_nested_attributes.rb +2 -2
- data/lib/brakeman/checks/check_number_to_currency.rb +2 -2
- data/lib/brakeman/checks/check_quote_table_name.rb +1 -1
- data/lib/brakeman/checks/check_redirect.rb +2 -10
- data/lib/brakeman/checks/check_render.rb +1 -1
- data/lib/brakeman/checks/check_render_dos.rb +1 -1
- data/lib/brakeman/checks/check_safe_buffer_manipulation.rb +1 -1
- data/lib/brakeman/checks/check_sanitize_methods.rb +1 -1
- data/lib/brakeman/checks/check_select_tag.rb +1 -1
- data/lib/brakeman/checks/check_select_vulnerability.rb +2 -2
- data/lib/brakeman/checks/check_session_settings.rb +1 -2
- data/lib/brakeman/checks/check_simple_format.rb +2 -2
- data/lib/brakeman/checks/check_single_quotes.rb +3 -3
- data/lib/brakeman/checks/check_skip_before_filter.rb +5 -7
- data/lib/brakeman/checks/check_sql.rb +10 -14
- data/lib/brakeman/checks/check_sql_cves.rb +4 -4
- data/lib/brakeman/checks/check_ssl_verify.rb +27 -9
- data/lib/brakeman/checks/check_strip_tags.rb +5 -5
- data/lib/brakeman/checks/check_symbol_dos_cve.rb +1 -1
- data/lib/brakeman/checks/check_translate_bug.rb +3 -4
- data/lib/brakeman/checks/check_unscoped_find.rb +1 -1
- data/lib/brakeman/checks/check_validation_regex.rb +2 -2
- data/lib/brakeman/checks/check_xml_dos.rb +1 -1
- data/lib/brakeman/checks/check_yaml_parsing.rb +1 -1
- data/lib/brakeman/file_parser.rb +1 -0
- data/lib/brakeman/parsers/template_parser.rb +6 -5
- data/lib/brakeman/processor.rb +7 -7
- data/lib/brakeman/processors/alias_processor.rb +30 -12
- data/lib/brakeman/processors/base_processor.rb +4 -8
- data/lib/brakeman/processors/controller_alias_processor.rb +33 -132
- data/lib/brakeman/processors/controller_processor.rb +29 -53
- data/lib/brakeman/processors/erb_template_processor.rb +4 -6
- data/lib/brakeman/processors/erubis_template_processor.rb +8 -11
- data/lib/brakeman/processors/gem_processor.rb +19 -35
- data/lib/brakeman/processors/haml_template_processor.rb +10 -12
- data/lib/brakeman/processors/lib/find_all_calls.rb +3 -5
- data/lib/brakeman/processors/lib/find_call.rb +2 -2
- data/lib/brakeman/processors/lib/find_return_value.rb +1 -1
- data/lib/brakeman/processors/lib/rails2_config_processor.rb +7 -8
- data/lib/brakeman/processors/lib/rails3_config_processor.rb +6 -7
- data/lib/brakeman/processors/lib/render_helper.rb +15 -14
- data/lib/brakeman/processors/lib/render_path.rb +11 -5
- data/lib/brakeman/processors/library_processor.rb +13 -35
- data/lib/brakeman/processors/model_processor.rb +22 -64
- data/lib/brakeman/processors/output_processor.rb +1 -37
- data/lib/brakeman/processors/slim_template_processor.rb +6 -8
- data/lib/brakeman/processors/template_alias_processor.rb +9 -9
- data/lib/brakeman/processors/template_processor.rb +5 -9
- data/lib/brakeman/report/report_base.rb +7 -7
- data/lib/brakeman/report/report_html.rb +5 -7
- data/lib/brakeman/report/report_markdown.rb +4 -6
- data/lib/brakeman/report/report_table.rb +4 -6
- data/lib/brakeman/rescanner.rb +29 -31
- data/lib/brakeman/scanner.rb +17 -8
- data/lib/brakeman/tracker.rb +24 -34
- data/lib/brakeman/tracker/collection.rb +77 -0
- data/lib/brakeman/tracker/config.rb +93 -0
- data/lib/brakeman/tracker/controller.rb +161 -0
- data/lib/brakeman/tracker/library.rb +17 -0
- data/lib/brakeman/tracker/model.rb +90 -0
- data/lib/brakeman/tracker/template.rb +33 -0
- data/lib/brakeman/util.rb +17 -9
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +8 -9
- data/lib/ruby_parser/bm_sexp.rb +16 -16
- data/lib/ruby_parser/bm_sexp_processor.rb +1 -120
- metadata +42 -31
- checksums.yaml.gz.sig +0 -1
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5db4cee0910ab76ab868345145436bbf8817ab04
|
4
|
+
data.tar.gz: 7633c66f5638aadb0ee5a1619755ee17e5a92ad0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 28a4089b017d8ee189a47b0597b18fa567637eb14d79caeea1beb1963ca17aa6761353d9ce557927516a5ec1d07b7e362c375b24e5893d84b1de5bc9041595cf
|
7
|
+
data.tar.gz: ea2a2b35fc4c7b6777cea07a9297bfcd32abe5ceaf476f7872efd845e8fcedb713ca91a128c31452ef148965945d1412d78c09c9c78cfe4e95aa24a5f07048c0
|
data/CHANGES
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
# 3.1.0
|
2
|
+
|
3
|
+
* Add support for gems.rb/gems.locked
|
4
|
+
* Update render path information in JSON reports
|
5
|
+
* Remove renaming of several Sexp nodes
|
6
|
+
* Convert YAML config keys to symbols (Karl Glaser)
|
7
|
+
* Use railties version if rails gem is missing (Lucas Mazza)
|
8
|
+
* Warn about unverified SSL mode in Net::HTTP.start
|
9
|
+
* Add Model, Controller, Template, Config classes internally
|
10
|
+
* Report file being parsed in debug output
|
11
|
+
* Update dependencies to Ruby 1.8 incompatible versions
|
12
|
+
* Treat Array.new and Hash.new as arrays/hashes
|
13
|
+
* Fix handling of string concatenation with existing string
|
14
|
+
* Treat html_safe like raw()
|
15
|
+
* Fix low confidence XSS warning code
|
16
|
+
* Avoid warning on path creation methods in link_to
|
17
|
+
* Expand safe methods to match methods with targets
|
18
|
+
* Avoid duplicate eval() warnings
|
19
|
+
|
1
20
|
# 3.0.5
|
2
21
|
|
3
22
|
* Fix check for CVE-2015-3227
|
data/README.md
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
[![Brakeman Logo](http://brakemanscanner.org/images/logo_medium.png)](http://brakemanscanner.org/)
|
2
2
|
|
3
|
-
[![
|
4
|
-
|
5
|
-
[![
|
6
|
-
Climate](https://codeclimate.com/github/presidentbeef/brakeman.png)](https://codeclimate.com/github/presidentbeef/brakeman)
|
3
|
+
[![Build Status](https://travis-ci.org/presidentbeef/brakeman.svg?branch=master)](https://travis-ci.org/presidentbeef/brakeman)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/presidentbeef/brakeman/badges/gpa.svg)](https://codeclimate.com/github/presidentbeef/brakeman)
|
5
|
+
[![Test Coverage](https://codeclimate.com/github/presidentbeef/brakeman/badges/coverage.svg)](https://codeclimate.com/github/presidentbeef/brakeman/coverage)
|
7
6
|
|
8
7
|
# Brakeman
|
9
8
|
|
@@ -130,15 +129,6 @@ The default config locations are `./config/brakeman.yml`, `~/.brakeman/config.ym
|
|
130
129
|
|
131
130
|
The `-c` option can be used to specify a configuration file to use.
|
132
131
|
|
133
|
-
# For Slim Users
|
134
|
-
|
135
|
-
[Slim v3.0.0](https://github.com/slim-template/slim/blob/master/CHANGES#L12) dropped support for Ruby 1.8.7. Install a version of [`slim`](http://slim-lang.com/) compatible with your Ruby.
|
136
|
-
|
137
|
-
| Ruby Version | `Gemfile` | Command Line |
|
138
|
-
|--------------|-----------------------|----------------------------------------|
|
139
|
-
| Ruby 1.8.7 | `gem 'slim', '< 3.0'` | `$ gem install slim --version '< 3.0'` |
|
140
|
-
| Ruby 1.9+ | `gem 'slim'` | `$ gem install slim` |
|
141
|
-
|
142
132
|
# Continuous Integration
|
143
133
|
|
144
134
|
There is a [plugin available](http://brakemanscanner.org/docs/jenkins/) for Jenkins/Hudson.
|
data/lib/brakeman.rb
CHANGED
@@ -99,6 +99,9 @@ module Brakeman
|
|
99
99
|
|
100
100
|
if options
|
101
101
|
options.each { |k, v| options[k] = Set.new v if v.is_a? Array }
|
102
|
+
|
103
|
+
# After parsing the yaml config file for options, convert any string keys into symbols.
|
104
|
+
options.keys.select {|k| k.is_a? String}.map {|k| k.to_sym }.each {|k| options[k] = options[k.to_s]; options.delete(k.to_s) }
|
102
105
|
|
103
106
|
# notify if options[:quiet] and quiet is nil||false
|
104
107
|
notify "[Notice] Using configuration in #{config}" unless (options[:quiet] || quiet)
|
@@ -39,8 +39,9 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
39
39
|
|
40
40
|
#Add result to result list, which is used to check for duplicates
|
41
41
|
def add_result result, location = nil
|
42
|
-
location ||= (@current_template && @current_template
|
42
|
+
location ||= (@current_template && @current_template.name) || @current_class || @current_module || @current_set || result[:location][:class] || result[:location][:template]
|
43
43
|
location = location[:name] if location.is_a? Hash
|
44
|
+
location = location.name if location.is_a? Brakeman::Collection
|
44
45
|
location = location.to_sym
|
45
46
|
|
46
47
|
if result.is_a? Hash
|
@@ -115,7 +116,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
115
116
|
end
|
116
117
|
|
117
118
|
#Does not actually process string interpolation, but notes that it occurred.
|
118
|
-
def
|
119
|
+
def process_dstr exp
|
119
120
|
@string_interp = Match.new(:interp, exp)
|
120
121
|
process_default exp
|
121
122
|
end
|
@@ -138,36 +139,6 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
138
139
|
Brakeman::OutputProcessor.new.format(exp).gsub(/\r|\n/, "")
|
139
140
|
end
|
140
141
|
|
141
|
-
#Checks if the model inherits from parent,
|
142
|
-
def ancestor? model, parent, seen={}
|
143
|
-
return false unless model
|
144
|
-
|
145
|
-
seen[model[:name]] = true
|
146
|
-
if model[:parent] == parent || seen[model[:parent]]
|
147
|
-
true
|
148
|
-
elsif model[:parent]
|
149
|
-
ancestor? tracker.models[model[:parent]], parent, seen
|
150
|
-
else
|
151
|
-
false
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def unprotected_model? model
|
156
|
-
model[:attr_accessible].nil? and !parent_classes_protected?(model) and ancestor?(model, :"ActiveRecord::Base")
|
157
|
-
end
|
158
|
-
|
159
|
-
# go up the chain of parent classes to see if any have attr_accessible
|
160
|
-
def parent_classes_protected? model, seen={}
|
161
|
-
seen[model] = true
|
162
|
-
if model[:attr_accessible] or model[:includes].include? :"ActiveModel::ForbiddenAttributesProtection"
|
163
|
-
true
|
164
|
-
elsif parent = tracker.models[model[:parent]] and !seen[parent]
|
165
|
-
parent_classes_protected? parent, seen
|
166
|
-
else
|
167
|
-
false
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
142
|
#Checks if mass assignment is disabled globally in an initializer.
|
172
143
|
def mass_assign_disabled?
|
173
144
|
return @mass_assign_disabled unless @mass_assign_disabled.nil?
|
@@ -175,12 +146,10 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
175
146
|
@mass_assign_disabled = false
|
176
147
|
|
177
148
|
if version_between?("3.1.0", "3.9.9") and
|
178
|
-
tracker.config
|
179
|
-
tracker.config[:rails][:active_record][:whitelist_attributes] == Sexp.new(:true)
|
149
|
+
tracker.config.whitelist_attributes?
|
180
150
|
|
181
151
|
@mass_assign_disabled = true
|
182
|
-
elsif tracker.options[:rails4] && (!tracker.config
|
183
|
-
tracker.config[:rails][:active_record][:whitelist_attributes] == Sexp.new(:true)))
|
152
|
+
elsif tracker.options[:rails4] && (!tracker.config.has_gem?(:protected_attributes) || tracker.config.whitelist_attributes?)
|
184
153
|
|
185
154
|
@mass_assign_disabled = true
|
186
155
|
else
|
@@ -231,7 +200,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
231
200
|
#gem and still using hack above, so this is a separate check for
|
232
201
|
#including ActiveModel::ForbiddenAttributesProtection in
|
233
202
|
#ActiveRecord::Base in an initializer.
|
234
|
-
if not @mass_assign_disabled and version_between?("3.1.0", "3.9.9") and tracker.config
|
203
|
+
if not @mass_assign_disabled and version_between?("3.1.0", "3.9.9") and tracker.config.has_gem? :strong_parameters
|
235
204
|
matches = tracker.check_initializers([], :include)
|
236
205
|
forbidden_protection = Sexp.new(:colon2, Sexp.new(:const, :ActiveModel), :ForbiddenAttributesProtection)
|
237
206
|
|
@@ -267,9 +236,10 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
267
236
|
raise ArgumentError
|
268
237
|
end
|
269
238
|
|
270
|
-
location ||= (@current_template && @current_template
|
239
|
+
location ||= (@current_template && @current_template.name) || @current_class || @current_module || @current_set || result[:location][:class] || result[:location][:template]
|
271
240
|
|
272
241
|
location = location[:name] if location.is_a? Hash
|
242
|
+
location = location.name if location.is_a? Brakeman::Collection
|
273
243
|
location = location.to_sym
|
274
244
|
|
275
245
|
@results.each do |r|
|
@@ -328,7 +298,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
328
298
|
end
|
329
299
|
elsif sexp? exp
|
330
300
|
case exp.node_type
|
331
|
-
when :
|
301
|
+
when :dstr
|
332
302
|
exp.each do |e|
|
333
303
|
if sexp? e
|
334
304
|
match = has_immediate_user_input?(e)
|
@@ -336,7 +306,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
336
306
|
end
|
337
307
|
end
|
338
308
|
false
|
339
|
-
when :
|
309
|
+
when :evstr
|
340
310
|
if sexp? exp.value
|
341
311
|
if exp.value.node_type == :rlist
|
342
312
|
exp.value.each_sexp do |e|
|
@@ -390,14 +360,14 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
390
360
|
end
|
391
361
|
elsif sexp? exp
|
392
362
|
case exp.node_type
|
393
|
-
when :
|
363
|
+
when :dstr
|
394
364
|
exp.each do |e|
|
395
365
|
if sexp? e and match = has_immediate_model?(e, out)
|
396
366
|
return match
|
397
367
|
end
|
398
368
|
end
|
399
369
|
false
|
400
|
-
when :
|
370
|
+
when :evstr
|
401
371
|
if sexp? exp.value
|
402
372
|
if exp.value.node_type == :rlist
|
403
373
|
exp.value.each_sexp do |e|
|
@@ -456,7 +426,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
456
426
|
#
|
457
427
|
#If the Rails version is unknown, returns false.
|
458
428
|
def version_between? low_version, high_version, current_version = nil
|
459
|
-
current_version ||=
|
429
|
+
current_version ||= rails_version
|
460
430
|
return false unless current_version
|
461
431
|
|
462
432
|
version = current_version.split(".").map! { |n| n.to_i }
|
@@ -483,15 +453,17 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
483
453
|
end
|
484
454
|
|
485
455
|
def lts_version? version
|
486
|
-
tracker.config
|
487
|
-
version_between? version, "2.3.18.99", tracker.config
|
456
|
+
tracker.config.has_gem? :'railslts-version' and
|
457
|
+
version_between? version, "2.3.18.99", tracker.config.gem_version(:'railslts-version')
|
488
458
|
end
|
489
459
|
|
490
460
|
def gemfile_or_environment gem_name = :rails
|
491
|
-
if gem_name and info = tracker.config
|
461
|
+
if gem_name and info = tracker.config.get_gem(gem_name)
|
492
462
|
info
|
493
463
|
elsif @app_tree.exists?("Gemfile")
|
494
464
|
"Gemfile"
|
465
|
+
elsif @app_tree.exists?("gems.rb")
|
466
|
+
"gems.rb"
|
495
467
|
else
|
496
468
|
"config/environment.rb"
|
497
469
|
end
|
@@ -507,7 +479,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
507
479
|
@active_record_models = {}
|
508
480
|
|
509
481
|
tracker.models.each do |name, model|
|
510
|
-
if ancestor?
|
482
|
+
if model.ancestor? :"ActiveRecord::Base"
|
511
483
|
@active_record_models[name] = model
|
512
484
|
end
|
513
485
|
end
|
@@ -18,11 +18,11 @@ class Brakeman::CheckBasicAuth < Brakeman::BaseCheck
|
|
18
18
|
|
19
19
|
def check_basic_auth_filter
|
20
20
|
controllers = tracker.controllers.select do |name, c|
|
21
|
-
c
|
21
|
+
c.options[:http_basic_authenticate_with]
|
22
22
|
end
|
23
23
|
|
24
24
|
Hash[controllers].each do |name, controller|
|
25
|
-
controller
|
25
|
+
controller.options[:http_basic_authenticate_with].each do |call|
|
26
26
|
|
27
27
|
if pass = get_password(call) and string? pass
|
28
28
|
warn :controller => name,
|
@@ -31,7 +31,7 @@ class Brakeman::CheckBasicAuth < Brakeman::BaseCheck
|
|
31
31
|
:message => "Basic authentication password stored in source code",
|
32
32
|
:code => call,
|
33
33
|
:confidence => 0,
|
34
|
-
:file => controller
|
34
|
+
:file => controller.file
|
35
35
|
break
|
36
36
|
end
|
37
37
|
end
|
@@ -42,7 +42,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
42
42
|
|
43
43
|
@current_template = template
|
44
44
|
|
45
|
-
template
|
45
|
+
template.each_output do |out|
|
46
46
|
unless check_for_immediate_xss out
|
47
47
|
@matched = false
|
48
48
|
@mark = false
|
@@ -57,10 +57,16 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
57
57
|
|
58
58
|
if exp.node_type == :output
|
59
59
|
out = exp.value
|
60
|
-
elsif exp.node_type == :escaped_output
|
61
|
-
|
60
|
+
elsif exp.node_type == :escaped_output
|
61
|
+
if raw_call? exp
|
62
|
+
out = exp.value.first_arg
|
63
|
+
elsif html_safe_call? exp
|
64
|
+
out = exp.value.target
|
65
|
+
end
|
62
66
|
end
|
63
67
|
|
68
|
+
return if call? out and ignore_call? out.target, out.method
|
69
|
+
|
64
70
|
if input = has_immediate_user_input?(out)
|
65
71
|
add_result exp
|
66
72
|
|
@@ -141,8 +147,12 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
141
147
|
#Otherwise, ignore
|
142
148
|
def process_escaped_output exp
|
143
149
|
unless check_for_immediate_xss exp
|
144
|
-
if
|
145
|
-
|
150
|
+
if not duplicate? exp
|
151
|
+
if raw_call? exp
|
152
|
+
process exp.value.first_arg
|
153
|
+
elsif html_safe_call? exp
|
154
|
+
process exp.value.target
|
155
|
+
end
|
146
156
|
end
|
147
157
|
end
|
148
158
|
exp
|
@@ -171,11 +181,14 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
171
181
|
add_result exp
|
172
182
|
|
173
183
|
link_path = "cross_site_scripting"
|
184
|
+
warning_code = :cross_site_scripting
|
185
|
+
|
174
186
|
if @known_dangerous.include? exp.method
|
175
187
|
confidence = CONFIDENCE[:high]
|
176
188
|
if exp.method == :to_json
|
177
189
|
message += " in JSON hash"
|
178
190
|
link_path += "_to_json"
|
191
|
+
warning_code = :xss_to_json
|
179
192
|
end
|
180
193
|
else
|
181
194
|
confidence = CONFIDENCE[:low]
|
@@ -183,7 +196,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
183
196
|
|
184
197
|
warn :template => @current_template,
|
185
198
|
:warning_type => "Cross Site Scripting",
|
186
|
-
:warning_code =>
|
199
|
+
:warning_code => warning_code,
|
187
200
|
:message => message,
|
188
201
|
:code => exp,
|
189
202
|
:user_input => @matched.match,
|
@@ -239,7 +252,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
239
252
|
end
|
240
253
|
|
241
254
|
#Process as default
|
242
|
-
def
|
255
|
+
def process_dstr exp
|
243
256
|
process_default exp
|
244
257
|
end
|
245
258
|
|
@@ -301,9 +314,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
301
314
|
initializers = tracker.check_initializers :ActiveSupport, :escape_html_entities_in_json=
|
302
315
|
initializers.each {|result| json_escape_on = true?(result.call.first_arg) }
|
303
316
|
|
304
|
-
if tracker.config
|
305
|
-
true? tracker.config[:rails][:active_support][:escape_html_entities_in_json]
|
306
|
-
|
317
|
+
if tracker.config.escape_html_entities_in_json?
|
307
318
|
json_escape_on = true
|
308
319
|
elsif version_between? "4.0.0", "5.0.0"
|
309
320
|
json_escape_on = true
|
@@ -322,6 +333,10 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
322
333
|
exp.value.node_type == :call and exp.value.method == :raw
|
323
334
|
end
|
324
335
|
|
336
|
+
def html_safe_call? exp
|
337
|
+
exp.value.node_type == :call and exp.value.method == :html_safe
|
338
|
+
end
|
339
|
+
|
325
340
|
def ignore_call? target, method
|
326
341
|
ignored_method?(target, method) or
|
327
342
|
safe_input_attribute?(target, method) or
|
@@ -340,8 +355,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
340
355
|
end
|
341
356
|
|
342
357
|
def ignored_method? target, method
|
343
|
-
|
344
|
-
(@ignore_methods.include? method or method.to_s =~ IGNORE_LIKE)
|
358
|
+
@ignore_methods.include? method or method.to_s =~ IGNORE_LIKE
|
345
359
|
end
|
346
360
|
|
347
361
|
def cgi_escaped? target, method
|
@@ -74,7 +74,7 @@ class Brakeman::CheckDefaultRoutes < Brakeman::BaseCheck
|
|
74
74
|
|
75
75
|
warn :warning_type => "Remote Code Execution",
|
76
76
|
:warning_code => :CVE_2014_0130,
|
77
|
-
:message => "Rails #{
|
77
|
+
:message => "Rails #{rails_version} with globbing routes is vulnerable to directory traversal and remote code execution. Patch or upgrade to #{upgrade}",
|
78
78
|
:confidence => confidence,
|
79
79
|
:file => "#{tracker.app_path}/config/routes.rb",
|
80
80
|
:link => "http://matasano.com/research/AnatomyOfRailsVuln-CVE-2014-0130.pdf"
|
@@ -14,7 +14,7 @@ class Brakeman::CheckDetailedExceptions < Brakeman::BaseCheck
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def check_local_request_config
|
17
|
-
if true? tracker.config
|
17
|
+
if true? tracker.config.rails[:consider_all_requests_local]
|
18
18
|
warn :warning_type => "Information Disclosure",
|
19
19
|
:warning_code => :local_request_config,
|
20
20
|
:message => "Detailed exceptions are enabled in production",
|
@@ -25,7 +25,7 @@ class Brakeman::CheckDetailedExceptions < Brakeman::BaseCheck
|
|
25
25
|
|
26
26
|
def check_detailed_exceptions
|
27
27
|
tracker.controllers.each do |name, controller|
|
28
|
-
controller
|
28
|
+
controller.methods_public.each do |name, definition|
|
29
29
|
src = definition[:src]
|
30
30
|
body = src.body.last
|
31
31
|
next unless body
|
@@ -20,6 +20,9 @@ class Brakeman::CheckEvaluation < Brakeman::BaseCheck
|
|
20
20
|
|
21
21
|
#Warns if eval includes user input
|
22
22
|
def process_result result
|
23
|
+
return if duplicate? result or result[:call].original_line
|
24
|
+
add_result result
|
25
|
+
|
23
26
|
if input = include_user_input?(result[:call].arglist)
|
24
27
|
warn :result => result,
|
25
28
|
:warning_type => "Dangerous Eval",
|
@@ -82,10 +82,10 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def dangerous_open_arg? exp
|
85
|
-
if
|
85
|
+
if string_interp? exp
|
86
86
|
# Check for input at start of string
|
87
87
|
exp[1] == "" and
|
88
|
-
node_type? exp[2], :evstr
|
88
|
+
node_type? exp[2], :evstr and
|
89
89
|
has_immediate_user_input? exp[2]
|
90
90
|
else
|
91
91
|
has_immediate_user_input? exp
|
@@ -137,7 +137,7 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
|
|
137
137
|
e = e.target
|
138
138
|
end
|
139
139
|
|
140
|
-
if node_type? e, :or, :evstr, :
|
140
|
+
if node_type? e, :or, :evstr, :dstr
|
141
141
|
if res = dangerous?(e)
|
142
142
|
return res
|
143
143
|
end
|
@@ -22,7 +22,7 @@ class Brakeman::CheckFileDisclosure < Brakeman::BaseCheck
|
|
22
22
|
if fix_version and serves_static_assets?
|
23
23
|
warn :warning_type => "File Access",
|
24
24
|
:warning_code => :CVE_2014_7829,
|
25
|
-
:message => "Rails #{
|
25
|
+
:message => "Rails #{rails_version} has a file existence disclosure. Upgrade to #{fix_version} or disable serving static assets",
|
26
26
|
:confidence => CONFIDENCE[:high],
|
27
27
|
:gem_info => gemfile_or_environment,
|
28
28
|
:link_path => "https://groups.google.com/d/msg/rubyonrails-security/23fiuwb1NBA/MQVM1-5GkPMJ"
|
@@ -30,6 +30,6 @@ class Brakeman::CheckFileDisclosure < Brakeman::BaseCheck
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def serves_static_assets?
|
33
|
-
true? tracker.config
|
33
|
+
true? tracker.config.rails[:serve_static_assets]
|
34
34
|
end
|
35
35
|
end
|
@@ -11,34 +11,31 @@ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
|
|
11
11
|
|
12
12
|
def run_check
|
13
13
|
app_controller = tracker.controllers[:ApplicationController]
|
14
|
+
return unless app_controller and app_controller.ancestor? :"ActionController::Base"
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
if tracker.config[:rails][:action_controller] and
|
18
|
-
tracker.config[:rails][:action_controller][:allow_forgery_protection] == Sexp.new(:false)
|
19
|
-
|
16
|
+
if tracker.config.allow_forgery_protection?
|
20
17
|
warn :controller => :ApplicationController,
|
21
18
|
:warning_type => "Cross-Site Request Forgery",
|
22
19
|
:warning_code => :csrf_protection_disabled,
|
23
20
|
:message => "Forgery protection is disabled",
|
24
21
|
:confidence => CONFIDENCE[:high],
|
25
|
-
:file => app_controller
|
22
|
+
:file => app_controller.file
|
26
23
|
|
27
|
-
elsif app_controller and not app_controller
|
24
|
+
elsif app_controller and not app_controller.protect_from_forgery?
|
28
25
|
|
29
26
|
warn :controller => :ApplicationController,
|
30
27
|
:warning_type => "Cross-Site Request Forgery",
|
31
28
|
:warning_code => :csrf_protection_missing,
|
32
29
|
:message => "'protect_from_forgery' should be called in ApplicationController",
|
33
30
|
:confidence => CONFIDENCE[:high],
|
34
|
-
:file => app_controller
|
31
|
+
:file => app_controller.file
|
35
32
|
|
36
33
|
elsif version_between? "2.1.0", "2.3.10"
|
37
34
|
|
38
35
|
warn :controller => :ApplicationController,
|
39
36
|
:warning_type => "Cross-Site Request Forgery",
|
40
37
|
:warning_code => :CVE_2011_0447,
|
41
|
-
:message => "CSRF protection is flawed in unpatched versions of Rails #{
|
38
|
+
:message => "CSRF protection is flawed in unpatched versions of Rails #{rails_version} (CVE-2011-0447). Upgrade to 2.3.11 or apply patches as needed",
|
42
39
|
:confidence => CONFIDENCE[:high],
|
43
40
|
:gem_info => gemfile_or_environment,
|
44
41
|
:link_path => "https://groups.google.com/d/topic/rubyonrails-security/LZWjzCPgNmU/discussion"
|
@@ -48,11 +45,11 @@ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
|
|
48
45
|
warn :controller => :ApplicationController,
|
49
46
|
:warning_type => "Cross-Site Request Forgery",
|
50
47
|
:warning_code => :CVE_2011_0447,
|
51
|
-
:message => "CSRF protection is flawed in unpatched versions of Rails #{
|
48
|
+
:message => "CSRF protection is flawed in unpatched versions of Rails #{rails_version} (CVE-2011-0447). Upgrade to 3.0.4 or apply patches as needed",
|
52
49
|
:confidence => CONFIDENCE[:high],
|
53
50
|
:gem_info => gemfile_or_environment,
|
54
51
|
:link_path => "https://groups.google.com/d/topic/rubyonrails-security/LZWjzCPgNmU/discussion"
|
55
|
-
elsif version_between? "4.0.0", "100.0.0" and forgery_opts = app_controller
|
52
|
+
elsif version_between? "4.0.0", "100.0.0" and forgery_opts = app_controller.options[:protect_from_forgery]
|
56
53
|
|
57
54
|
unless forgery_opts.is_a?(Array) and sexp?(forgery_opts.first) and
|
58
55
|
access_arg = hash_access(forgery_opts.first.first_arg, :with) and access_arg.value == :exception
|
@@ -63,7 +60,7 @@ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
|
|
63
60
|
:warning_code => :csrf_not_protected_by_raising_exception,
|
64
61
|
:message => "protect_from_forgery should be configured with 'with: :exception'",
|
65
62
|
:confidence => CONFIDENCE[:med],
|
66
|
-
:file => app_controller
|
63
|
+
:file => app_controller.file
|
67
64
|
}
|
68
65
|
|
69
66
|
args.merge!(:code => forgery_opts.first) if forgery_opts.is_a?(Array)
|