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,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