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.
- checksums.yaml +7 -0
- data/CHANGES +872 -0
- data/FEATURES +16 -0
- data/README.md +169 -0
- data/WARNING_TYPES +95 -0
- data/bin/brakeman +89 -0
- data/lib/brakeman.rb +495 -0
- data/lib/brakeman/app_tree.rb +161 -0
- data/lib/brakeman/brakeman.rake +17 -0
- data/lib/brakeman/call_index.rb +219 -0
- data/lib/brakeman/checks.rb +191 -0
- data/lib/brakeman/checks/base_check.rb +518 -0
- data/lib/brakeman/checks/check_basic_auth.rb +88 -0
- data/lib/brakeman/checks/check_basic_auth_timing_attack.rb +33 -0
- data/lib/brakeman/checks/check_content_tag.rb +160 -0
- data/lib/brakeman/checks/check_create_with.rb +75 -0
- data/lib/brakeman/checks/check_cross_site_scripting.rb +385 -0
- data/lib/brakeman/checks/check_default_routes.rb +86 -0
- data/lib/brakeman/checks/check_deserialize.rb +57 -0
- data/lib/brakeman/checks/check_detailed_exceptions.rb +55 -0
- data/lib/brakeman/checks/check_digest_dos.rb +38 -0
- data/lib/brakeman/checks/check_dynamic_finders.rb +49 -0
- data/lib/brakeman/checks/check_escape_function.rb +21 -0
- data/lib/brakeman/checks/check_evaluation.rb +36 -0
- data/lib/brakeman/checks/check_execute.rb +167 -0
- data/lib/brakeman/checks/check_file_access.rb +63 -0
- data/lib/brakeman/checks/check_file_disclosure.rb +35 -0
- data/lib/brakeman/checks/check_filter_skipping.rb +31 -0
- data/lib/brakeman/checks/check_forgery_setting.rb +74 -0
- data/lib/brakeman/checks/check_header_dos.rb +31 -0
- data/lib/brakeman/checks/check_i18n_xss.rb +48 -0
- data/lib/brakeman/checks/check_jruby_xml.rb +38 -0
- data/lib/brakeman/checks/check_json_encoding.rb +47 -0
- data/lib/brakeman/checks/check_json_parsing.rb +107 -0
- data/lib/brakeman/checks/check_link_to.rb +132 -0
- data/lib/brakeman/checks/check_link_to_href.rb +115 -0
- data/lib/brakeman/checks/check_mail_to.rb +49 -0
- data/lib/brakeman/checks/check_mass_assignment.rb +198 -0
- data/lib/brakeman/checks/check_mime_type_dos.rb +39 -0
- data/lib/brakeman/checks/check_model_attr_accessible.rb +55 -0
- data/lib/brakeman/checks/check_model_attributes.rb +119 -0
- data/lib/brakeman/checks/check_model_serialize.rb +67 -0
- data/lib/brakeman/checks/check_nested_attributes.rb +38 -0
- data/lib/brakeman/checks/check_nested_attributes_bypass.rb +58 -0
- data/lib/brakeman/checks/check_number_to_currency.rb +74 -0
- data/lib/brakeman/checks/check_quote_table_name.rb +40 -0
- data/lib/brakeman/checks/check_redirect.rb +215 -0
- data/lib/brakeman/checks/check_regex_dos.rb +69 -0
- data/lib/brakeman/checks/check_render.rb +92 -0
- data/lib/brakeman/checks/check_render_dos.rb +37 -0
- data/lib/brakeman/checks/check_render_inline.rb +54 -0
- data/lib/brakeman/checks/check_response_splitting.rb +21 -0
- data/lib/brakeman/checks/check_route_dos.rb +42 -0
- data/lib/brakeman/checks/check_safe_buffer_manipulation.rb +31 -0
- data/lib/brakeman/checks/check_sanitize_methods.rb +79 -0
- data/lib/brakeman/checks/check_secrets.rb +40 -0
- data/lib/brakeman/checks/check_select_tag.rb +60 -0
- data/lib/brakeman/checks/check_select_vulnerability.rb +60 -0
- data/lib/brakeman/checks/check_send.rb +48 -0
- data/lib/brakeman/checks/check_send_file.rb +19 -0
- data/lib/brakeman/checks/check_session_manipulation.rb +36 -0
- data/lib/brakeman/checks/check_session_settings.rb +170 -0
- data/lib/brakeman/checks/check_simple_format.rb +59 -0
- data/lib/brakeman/checks/check_single_quotes.rb +101 -0
- data/lib/brakeman/checks/check_skip_before_filter.rb +60 -0
- data/lib/brakeman/checks/check_sql.rb +660 -0
- data/lib/brakeman/checks/check_sql_cves.rb +101 -0
- data/lib/brakeman/checks/check_ssl_verify.rb +49 -0
- data/lib/brakeman/checks/check_strip_tags.rb +89 -0
- data/lib/brakeman/checks/check_symbol_dos.rb +64 -0
- data/lib/brakeman/checks/check_symbol_dos_cve.rb +30 -0
- data/lib/brakeman/checks/check_translate_bug.rb +45 -0
- data/lib/brakeman/checks/check_unsafe_reflection.rb +51 -0
- data/lib/brakeman/checks/check_unscoped_find.rb +41 -0
- data/lib/brakeman/checks/check_validation_regex.rb +116 -0
- data/lib/brakeman/checks/check_weak_hash.rb +151 -0
- data/lib/brakeman/checks/check_without_protection.rb +80 -0
- data/lib/brakeman/checks/check_xml_dos.rb +51 -0
- data/lib/brakeman/checks/check_yaml_parsing.rb +121 -0
- data/lib/brakeman/differ.rb +66 -0
- data/lib/brakeman/file_parser.rb +50 -0
- data/lib/brakeman/format/style.css +133 -0
- data/lib/brakeman/options.rb +301 -0
- data/lib/brakeman/parsers/rails2_erubis.rb +6 -0
- data/lib/brakeman/parsers/rails2_xss_plugin_erubis.rb +48 -0
- data/lib/brakeman/parsers/rails3_erubis.rb +74 -0
- data/lib/brakeman/parsers/template_parser.rb +89 -0
- data/lib/brakeman/processor.rb +102 -0
- data/lib/brakeman/processors/alias_processor.rb +1013 -0
- data/lib/brakeman/processors/base_processor.rb +277 -0
- data/lib/brakeman/processors/config_processor.rb +14 -0
- data/lib/brakeman/processors/controller_alias_processor.rb +273 -0
- data/lib/brakeman/processors/controller_processor.rb +326 -0
- data/lib/brakeman/processors/erb_template_processor.rb +80 -0
- data/lib/brakeman/processors/erubis_template_processor.rb +104 -0
- data/lib/brakeman/processors/gem_processor.rb +57 -0
- data/lib/brakeman/processors/haml_template_processor.rb +190 -0
- data/lib/brakeman/processors/lib/basic_processor.rb +37 -0
- data/lib/brakeman/processors/lib/find_all_calls.rb +223 -0
- data/lib/brakeman/processors/lib/find_call.rb +183 -0
- data/lib/brakeman/processors/lib/find_return_value.rb +134 -0
- data/lib/brakeman/processors/lib/processor_helper.rb +75 -0
- data/lib/brakeman/processors/lib/rails2_config_processor.rb +145 -0
- data/lib/brakeman/processors/lib/rails2_route_processor.rb +313 -0
- data/lib/brakeman/processors/lib/rails3_config_processor.rb +132 -0
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +308 -0
- data/lib/brakeman/processors/lib/render_helper.rb +181 -0
- data/lib/brakeman/processors/lib/render_path.rb +107 -0
- data/lib/brakeman/processors/lib/route_helper.rb +68 -0
- data/lib/brakeman/processors/lib/safe_call_helper.rb +16 -0
- data/lib/brakeman/processors/library_processor.rb +119 -0
- data/lib/brakeman/processors/model_processor.rb +191 -0
- data/lib/brakeman/processors/output_processor.rb +171 -0
- data/lib/brakeman/processors/route_processor.rb +17 -0
- data/lib/brakeman/processors/slim_template_processor.rb +107 -0
- data/lib/brakeman/processors/template_alias_processor.rb +116 -0
- data/lib/brakeman/processors/template_processor.rb +74 -0
- data/lib/brakeman/report.rb +78 -0
- data/lib/brakeman/report/config/remediation.yml +71 -0
- data/lib/brakeman/report/ignore/config.rb +135 -0
- data/lib/brakeman/report/ignore/interactive.rb +311 -0
- data/lib/brakeman/report/renderer.rb +24 -0
- data/lib/brakeman/report/report_base.rb +286 -0
- data/lib/brakeman/report/report_codeclimate.rb +70 -0
- data/lib/brakeman/report/report_csv.rb +55 -0
- data/lib/brakeman/report/report_hash.rb +23 -0
- data/lib/brakeman/report/report_html.rb +216 -0
- data/lib/brakeman/report/report_json.rb +42 -0
- data/lib/brakeman/report/report_markdown.rb +156 -0
- data/lib/brakeman/report/report_table.rb +107 -0
- data/lib/brakeman/report/report_tabs.rb +17 -0
- data/lib/brakeman/report/templates/controller_overview.html.erb +22 -0
- data/lib/brakeman/report/templates/controller_warnings.html.erb +21 -0
- data/lib/brakeman/report/templates/error_overview.html.erb +29 -0
- data/lib/brakeman/report/templates/header.html.erb +58 -0
- data/lib/brakeman/report/templates/ignored_warnings.html.erb +25 -0
- data/lib/brakeman/report/templates/model_warnings.html.erb +21 -0
- data/lib/brakeman/report/templates/overview.html.erb +38 -0
- data/lib/brakeman/report/templates/security_warnings.html.erb +23 -0
- data/lib/brakeman/report/templates/template_overview.html.erb +21 -0
- data/lib/brakeman/report/templates/view_warnings.html.erb +34 -0
- data/lib/brakeman/report/templates/warning_overview.html.erb +17 -0
- data/lib/brakeman/rescanner.rb +483 -0
- data/lib/brakeman/scanner.rb +317 -0
- data/lib/brakeman/tracker.rb +347 -0
- data/lib/brakeman/tracker/collection.rb +93 -0
- data/lib/brakeman/tracker/config.rb +101 -0
- data/lib/brakeman/tracker/constants.rb +101 -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 +481 -0
- data/lib/brakeman/version.rb +3 -0
- data/lib/brakeman/warning.rb +255 -0
- data/lib/brakeman/warning_codes.rb +111 -0
- data/lib/ruby_parser/bm_sexp.rb +610 -0
- data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
- metadata +362 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
class Brakeman::CheckMimeTypeDoS < Brakeman::BaseCheck
|
|
4
|
+
Brakeman::Checks.add self
|
|
5
|
+
|
|
6
|
+
@description = "Checks for mime type denial of service (CVE-2016-0751)"
|
|
7
|
+
|
|
8
|
+
def run_check
|
|
9
|
+
fix_version = case
|
|
10
|
+
when version_between?("3.0.0", "3.2.22")
|
|
11
|
+
"3.2.22.1"
|
|
12
|
+
when version_between?("4.0.0", "4.1.14")
|
|
13
|
+
"4.1.14.1"
|
|
14
|
+
when version_between?("4.2.0", "4.2.5")
|
|
15
|
+
"4.2.5.1"
|
|
16
|
+
else
|
|
17
|
+
return
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
return if has_workaround?
|
|
21
|
+
|
|
22
|
+
message = "Rails #{rails_version} is vulnerable to denial of service via mime type caching (CVE-2016-0751). Upgrade to Rails version #{fix_version}"
|
|
23
|
+
|
|
24
|
+
warn :warning_type => "Denial of Service",
|
|
25
|
+
:warning_code => :CVE_2016_0751,
|
|
26
|
+
:message => message,
|
|
27
|
+
:confidence => CONFIDENCE[:med],
|
|
28
|
+
:gem_info => gemfile_or_environment,
|
|
29
|
+
:link_path => "https://groups.google.com/d/msg/rubyonrails-security/9oLY_FCzvoc/w9oI9XxbFQAJ"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def has_workaround?
|
|
33
|
+
tracker.check_initializers(:Mime, :const_set).any? do |match|
|
|
34
|
+
arg = match.call.first_arg
|
|
35
|
+
|
|
36
|
+
symbol? arg and arg.value == :LOOKUP
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
# Author: Paul Deardorff (themetric)
|
|
4
|
+
# Checks models to see if important foreign keys
|
|
5
|
+
# or attributes are exposed as attr_accessible when
|
|
6
|
+
# they probably shouldn't be.
|
|
7
|
+
|
|
8
|
+
class Brakeman::CheckModelAttrAccessible < Brakeman::BaseCheck
|
|
9
|
+
Brakeman::Checks.add self
|
|
10
|
+
|
|
11
|
+
@description = "Reports models which have dangerous attributes defined under the attr_accessible whitelist."
|
|
12
|
+
|
|
13
|
+
SUSP_ATTRS = [
|
|
14
|
+
[:admin, CONFIDENCE[:high]], # Very dangerous unless some Rails authorization used
|
|
15
|
+
[:role, CONFIDENCE[:med]],
|
|
16
|
+
[:banned, CONFIDENCE[:med]],
|
|
17
|
+
[:account_id, CONFIDENCE[:high]],
|
|
18
|
+
[/\S*_id(s?)\z/, CONFIDENCE[:low]] # All other foreign keys have weak/low confidence
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
def run_check
|
|
22
|
+
check_models do |name, model|
|
|
23
|
+
model.attr_accessible.each do |attribute|
|
|
24
|
+
next if role_limited? model, attribute
|
|
25
|
+
|
|
26
|
+
SUSP_ATTRS.each do |susp_attr, confidence|
|
|
27
|
+
if susp_attr.is_a?(Regexp) and susp_attr =~ attribute.to_s or susp_attr == attribute
|
|
28
|
+
warn :model => name,
|
|
29
|
+
:file => model.file,
|
|
30
|
+
:warning_type => "Mass Assignment",
|
|
31
|
+
:warning_code => :dangerous_attr_accessible,
|
|
32
|
+
:message => "Potentially dangerous attribute available for mass assignment",
|
|
33
|
+
:confidence => confidence,
|
|
34
|
+
:code => Sexp.new(:lit, attribute)
|
|
35
|
+
break # Prevent from matching single attr multiple times
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def role_limited? model, attribute
|
|
43
|
+
role_accessible = model.role_accessible
|
|
44
|
+
return if role_accessible.nil?
|
|
45
|
+
role_accessible.include? attribute
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def check_models
|
|
49
|
+
tracker.models.each do |name, model|
|
|
50
|
+
if !model.attr_accessible.nil?
|
|
51
|
+
yield name, model
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
#Check if mass assignment is used with models
|
|
4
|
+
#which inherit from ActiveRecord::Base.
|
|
5
|
+
#
|
|
6
|
+
#If tracker.options[:collapse_mass_assignment] is +true+ (default), all models
|
|
7
|
+
#which do not use attr_accessible will be reported in a single warning
|
|
8
|
+
class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
|
|
9
|
+
Brakeman::Checks.add self
|
|
10
|
+
|
|
11
|
+
@description = "Reports models which do not use attr_restricted and warns on models that use attr_protected"
|
|
12
|
+
|
|
13
|
+
def run_check
|
|
14
|
+
return if mass_assign_disabled?
|
|
15
|
+
|
|
16
|
+
#Roll warnings into one warning for all models
|
|
17
|
+
if tracker.options[:collapse_mass_assignment]
|
|
18
|
+
no_accessible_names = []
|
|
19
|
+
protected_names = []
|
|
20
|
+
|
|
21
|
+
check_models do |name, model|
|
|
22
|
+
if model.attr_protected.nil?
|
|
23
|
+
no_accessible_names << name.to_s
|
|
24
|
+
elsif not tracker.options[:ignore_attr_protected]
|
|
25
|
+
protected_names << name.to_s
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
unless no_accessible_names.empty?
|
|
30
|
+
warn :model => no_accessible_names.sort.join(", "),
|
|
31
|
+
:warning_type => "Attribute Restriction",
|
|
32
|
+
:warning_code => :no_attr_accessible,
|
|
33
|
+
:message => "Mass assignment is not restricted using attr_accessible",
|
|
34
|
+
:confidence => CONFIDENCE[:high]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
unless protected_names.empty?
|
|
38
|
+
message, confidence, link = check_for_attr_protected_bypass
|
|
39
|
+
|
|
40
|
+
if link
|
|
41
|
+
warning_code = :CVE_2013_0276
|
|
42
|
+
else
|
|
43
|
+
warning_code = :attr_protected_used
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
warn :model => protected_names.sort.join(", "),
|
|
47
|
+
:warning_type => "Attribute Restriction",
|
|
48
|
+
:warning_code => warning_code,
|
|
49
|
+
:message => message,
|
|
50
|
+
:confidence => confidence,
|
|
51
|
+
:link => link
|
|
52
|
+
end
|
|
53
|
+
else #Output one warning per model
|
|
54
|
+
|
|
55
|
+
check_models do |name, model|
|
|
56
|
+
if model.attr_protected.nil?
|
|
57
|
+
warn :model => name,
|
|
58
|
+
:file => model.file,
|
|
59
|
+
:line => model.top_line,
|
|
60
|
+
:warning_type => "Attribute Restriction",
|
|
61
|
+
:warning_code => :no_attr_accessible,
|
|
62
|
+
:message => "Mass assignment is not restricted using attr_accessible",
|
|
63
|
+
:confidence => CONFIDENCE[:high]
|
|
64
|
+
elsif not tracker.options[:ignore_attr_protected]
|
|
65
|
+
message, confidence, link = check_for_attr_protected_bypass
|
|
66
|
+
|
|
67
|
+
if link
|
|
68
|
+
warning_code = :CVE_2013_0276
|
|
69
|
+
else
|
|
70
|
+
warning_code = :attr_protected_used
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
warn :model => name,
|
|
74
|
+
:file => model.file,
|
|
75
|
+
:line => model.attr_protected.first.line,
|
|
76
|
+
:warning_type => "Attribute Restriction",
|
|
77
|
+
:warning_code => warning_code,
|
|
78
|
+
:message => message,
|
|
79
|
+
:confidence => confidence
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def check_models
|
|
86
|
+
tracker.models.each do |name, model|
|
|
87
|
+
if model.unprotected_model?
|
|
88
|
+
yield name, model
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def check_for_attr_protected_bypass
|
|
94
|
+
upgrade_version = case
|
|
95
|
+
when version_between?("2.0.0", "2.3.16")
|
|
96
|
+
"2.3.17"
|
|
97
|
+
when version_between?("3.0.0", "3.0.99")
|
|
98
|
+
"3.2.11"
|
|
99
|
+
when version_between?("3.1.0", "3.1.10")
|
|
100
|
+
"3.1.11"
|
|
101
|
+
when version_between?("3.2.0", "3.2.11")
|
|
102
|
+
"3.2.12"
|
|
103
|
+
else
|
|
104
|
+
nil
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
if upgrade_version
|
|
108
|
+
message = "attr_protected is bypassable in #{rails_version}, use attr_accessible or upgrade to #{upgrade_version}"
|
|
109
|
+
confidence = CONFIDENCE[:high]
|
|
110
|
+
link = "https://groups.google.com/d/topic/rubyonrails-security/AFBKNY7VSH8/discussion"
|
|
111
|
+
else
|
|
112
|
+
message = "attr_accessible is recommended over attr_protected"
|
|
113
|
+
confidence = CONFIDENCE[:med]
|
|
114
|
+
link = nil
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
return message, confidence, link
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
class Brakeman::CheckModelSerialize < Brakeman::BaseCheck
|
|
4
|
+
Brakeman::Checks.add self
|
|
5
|
+
|
|
6
|
+
@description = "Report uses of serialize in versions vulnerable to CVE-2013-0277"
|
|
7
|
+
|
|
8
|
+
def run_check
|
|
9
|
+
@upgrade_version = case
|
|
10
|
+
when version_between?("2.0.0", "2.3.16")
|
|
11
|
+
"2.3.17"
|
|
12
|
+
when version_between?("3.0.0", "3.0.99")
|
|
13
|
+
"3.2.11"
|
|
14
|
+
else
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
return unless @upgrade_version
|
|
19
|
+
|
|
20
|
+
tracker.models.each do |name, model|
|
|
21
|
+
check_for_serialize model
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#High confidence warning on serialized, unprotected attributes.
|
|
26
|
+
#Medium confidence warning for serialized, protected attributes.
|
|
27
|
+
def check_for_serialize model
|
|
28
|
+
if serialized_attrs = model.options[:serialize]
|
|
29
|
+
attrs = Set.new
|
|
30
|
+
|
|
31
|
+
serialized_attrs.each do |arglist|
|
|
32
|
+
arglist.each do |arg|
|
|
33
|
+
attrs << arg if symbol? arg
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if unsafe_attrs = model.attr_accessible
|
|
38
|
+
attrs.delete_if { |attr| not unsafe_attrs.include? attr.value }
|
|
39
|
+
elsif protected_attrs = model.attr_protected
|
|
40
|
+
safe_attrs = Set.new
|
|
41
|
+
|
|
42
|
+
protected_attrs.each do |arglist|
|
|
43
|
+
arglist.each do |arg|
|
|
44
|
+
safe_attrs << arg if symbol? arg
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
attrs.delete_if { |attr| safe_attrs.include? attr }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if attrs.empty?
|
|
52
|
+
confidence = CONFIDENCE[:med]
|
|
53
|
+
else
|
|
54
|
+
confidence = CONFIDENCE[:high]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
warn :model => model.name,
|
|
58
|
+
:warning_type => "Remote Code Execution",
|
|
59
|
+
:warning_code => :CVE_2013_0277,
|
|
60
|
+
:message => "Serialized attributes are vulnerable in Rails #{rails_version}, upgrade to #{@upgrade_version} or patch.",
|
|
61
|
+
:confidence => confidence,
|
|
62
|
+
:link => "https://groups.google.com/d/topic/rubyonrails-security/KtmwSbEpzrU/discussion",
|
|
63
|
+
:file => model.file,
|
|
64
|
+
:line => model.top_line
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
#Check for vulnerability in nested attributes in Rails 2.3.9 and 3.0.0
|
|
4
|
+
#http://groups.google.com/group/rubyonrails-security/browse_thread/thread/f9f913d328dafe0c
|
|
5
|
+
class Brakeman::CheckNestedAttributes < Brakeman::BaseCheck
|
|
6
|
+
Brakeman::Checks.add self
|
|
7
|
+
|
|
8
|
+
@description = "Checks for nested attributes vulnerability in Rails 2.3.9 and 3.0.0"
|
|
9
|
+
|
|
10
|
+
def run_check
|
|
11
|
+
version = rails_version
|
|
12
|
+
|
|
13
|
+
if (version == "2.3.9" or version == "3.0.0") and uses_nested_attributes?
|
|
14
|
+
message = "Vulnerability in nested attributes (CVE-2010-3933). Upgrade to Rails version "
|
|
15
|
+
|
|
16
|
+
if version == "2.3.9"
|
|
17
|
+
message << "2.3.10"
|
|
18
|
+
else
|
|
19
|
+
message << "3.0.1"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
warn :warning_type => "Nested Attributes",
|
|
23
|
+
:warning_code => :CVE_2010_3933,
|
|
24
|
+
:message => message,
|
|
25
|
+
:confidence => CONFIDENCE[:high],
|
|
26
|
+
:gem_info => gemfile_or_environment,
|
|
27
|
+
:link_path => "https://groups.google.com/d/topic/rubyonrails-security/-fkT0yja_gw/discussion"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def uses_nested_attributes?
|
|
32
|
+
active_record_models.each do |name, model|
|
|
33
|
+
return true if model.options[:accepts_nested_attributes_for]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
#https://groups.google.com/d/msg/rubyonrails-security/cawsWcQ6c8g/tegZtYdbFQAJ
|
|
4
|
+
class Brakeman::CheckNestedAttributesBypass < Brakeman::BaseCheck
|
|
5
|
+
Brakeman::Checks.add self
|
|
6
|
+
|
|
7
|
+
@description = "Checks for nested attributes vulnerability (CVE-2015-7577)"
|
|
8
|
+
|
|
9
|
+
def run_check
|
|
10
|
+
if version_between? "3.1.0", "3.2.22" or
|
|
11
|
+
version_between? "4.0.0", "4.1.14" or
|
|
12
|
+
version_between? "4.2.0", "4.2.5"
|
|
13
|
+
|
|
14
|
+
unless workaround?
|
|
15
|
+
check_nested_attributes
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def check_nested_attributes
|
|
21
|
+
active_record_models.each do |name, model|
|
|
22
|
+
if opts = model.options[:accepts_nested_attributes_for]
|
|
23
|
+
opts.each do |args|
|
|
24
|
+
if args.any? { |a| allow_destroy? a } and args.any? { |a| reject_if? a }
|
|
25
|
+
warn_about_nested_attributes name, model, args
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def warn_about_nested_attributes name, model, args
|
|
33
|
+
message = "Rails #{rails_version} does not call :reject_if option when :allow_destroy is false (CVE-2015-7577)"
|
|
34
|
+
|
|
35
|
+
warn :model => name,
|
|
36
|
+
:warning_type => "Nested Attributes",
|
|
37
|
+
:warning_code => :CVE_2015_7577,
|
|
38
|
+
:message => message,
|
|
39
|
+
:file => model.file,
|
|
40
|
+
:line => args.line,
|
|
41
|
+
:confidence => CONFIDENCE[:med],
|
|
42
|
+
:link_path => "https://groups.google.com/d/msg/rubyonrails-security/cawsWcQ6c8g/tegZtYdbFQAJ"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def allow_destroy? arg
|
|
46
|
+
hash? arg and
|
|
47
|
+
false? hash_access(arg, :allow_destroy)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def reject_if? arg
|
|
51
|
+
hash? arg and
|
|
52
|
+
hash_access(arg, :reject_if)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def workaround?
|
|
56
|
+
tracker.check_initializers([], :will_be_destroyed?).any?
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
class Brakeman::CheckNumberToCurrency < Brakeman::BaseCheck
|
|
4
|
+
Brakeman::Checks.add self
|
|
5
|
+
|
|
6
|
+
@description = "Checks for number helpers XSS vulnerabilities in certain versions"
|
|
7
|
+
|
|
8
|
+
def initialize(*)
|
|
9
|
+
super
|
|
10
|
+
@found_any = false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run_check
|
|
14
|
+
if version_between? "2.0.0", "2.3.18" or
|
|
15
|
+
version_between? "3.0.0", "3.2.16" or
|
|
16
|
+
version_between? "4.0.0", "4.0.2"
|
|
17
|
+
|
|
18
|
+
return if lts_version? "2.3.18.8"
|
|
19
|
+
|
|
20
|
+
check_number_helper_usage
|
|
21
|
+
generic_warning unless @found_any
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def generic_warning
|
|
26
|
+
message = "Rails #{rails_version} has a vulnerability in number helpers (CVE-2014-0081). Upgrade to Rails version "
|
|
27
|
+
|
|
28
|
+
if version_between? "2.3.0", "3.2.16"
|
|
29
|
+
message << "3.2.17"
|
|
30
|
+
else
|
|
31
|
+
message << "4.0.3"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
warn :warning_type => "Cross Site Scripting",
|
|
35
|
+
:warning_code => :CVE_2014_0081,
|
|
36
|
+
:message => message,
|
|
37
|
+
:confidence => CONFIDENCE[:med],
|
|
38
|
+
:gem_info => gemfile_or_environment,
|
|
39
|
+
:link_path => "https://groups.google.com/d/msg/ruby-security-ann/9WiRn2nhfq0/2K2KRB4LwCMJ"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def check_number_helper_usage
|
|
43
|
+
number_methods = [:number_to_currency, :number_to_percentage, :number_to_human]
|
|
44
|
+
tracker.find_call(:target => false, :methods => number_methods).each do |result|
|
|
45
|
+
arg = result[:call].second_arg
|
|
46
|
+
next unless arg
|
|
47
|
+
|
|
48
|
+
if not check_helper_option(result, arg) and hash? arg
|
|
49
|
+
hash_iterate(arg) do |key, value|
|
|
50
|
+
break if check_helper_option(result, value)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def check_helper_option result, exp
|
|
57
|
+
if match = (has_immediate_user_input? exp or has_immediate_model? exp)
|
|
58
|
+
warn_on_number_helper result, match
|
|
59
|
+
@found_any = true
|
|
60
|
+
else
|
|
61
|
+
false
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def warn_on_number_helper result, match
|
|
66
|
+
warn :result => result,
|
|
67
|
+
:warning_type => "Cross Site Scripting",
|
|
68
|
+
:warning_code => :CVE_2014_0081_call,
|
|
69
|
+
:message => "Format options in #{result[:call].method} are not safe in Rails #{rails_version}",
|
|
70
|
+
:confidence => CONFIDENCE[:high],
|
|
71
|
+
:link_path => "https://groups.google.com/d/msg/ruby-security-ann/9WiRn2nhfq0/2K2KRB4LwCMJ",
|
|
72
|
+
:user_input => match
|
|
73
|
+
end
|
|
74
|
+
end
|