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,63 @@
1
+ require 'brakeman/checks/base_check'
2
+ require 'brakeman/processors/lib/processor_helper'
3
+
4
+ #Checks for user input in methods which open or manipulate files
5
+ class Brakeman::CheckFileAccess < Brakeman::BaseCheck
6
+ Brakeman::Checks.add self
7
+
8
+ @description = "Finds possible file access using user input"
9
+
10
+ def run_check
11
+ Brakeman.debug "Finding possible file access"
12
+ methods = tracker.find_call :targets => [:Dir, :File, :IO, :Kernel, :"Net::FTP", :"Net::HTTP", :PStore, :Pathname, :Shell], :methods => [:[], :chdir, :chroot, :delete, :entries, :foreach, :glob, :install, :lchmod, :lchown, :link, :load, :load_file, :makedirs, :move, :new, :open, :read, :readlines, :rename, :rmdir, :safe_unlink, :symlink, :syscopy, :sysopen, :truncate, :unlink]
13
+
14
+ methods.concat tracker.find_call :target => :YAML, :methods => [:load_file, :parse_file]
15
+ methods.concat tracker.find_call :target => nil, :method => [:open]
16
+
17
+ Brakeman.debug "Finding calls to load()"
18
+ methods.concat tracker.find_call :target => false, :method => :load
19
+
20
+ Brakeman.debug "Finding calls using FileUtils"
21
+ methods.concat tracker.find_call :target => :FileUtils
22
+
23
+ Brakeman.debug "Processing found calls"
24
+ methods.each do |call|
25
+ process_result call
26
+ end
27
+ end
28
+
29
+ def process_result result
30
+ return if duplicate? result
31
+ add_result result
32
+ call = result[:call]
33
+ file_name = call.first_arg
34
+
35
+ if match = has_immediate_user_input?(file_name)
36
+ confidence = CONFIDENCE[:high]
37
+ elsif match = has_immediate_model?(file_name)
38
+ match = Match.new(:model, match)
39
+ confidence = CONFIDENCE[:med]
40
+ elsif tracker.options[:check_arguments] and
41
+ match = include_user_input?(file_name)
42
+
43
+ #Check for string building in file name
44
+ if call?(file_name) and (file_name.method == :+ or file_name.method == :<<)
45
+ confidence = CONFIDENCE[:high]
46
+ else
47
+ confidence = CONFIDENCE[:low]
48
+ end
49
+ end
50
+
51
+ if match
52
+ message = "#{friendly_type_of(match).capitalize} used in file name"
53
+
54
+ warn :result => result,
55
+ :warning_type => "File Access",
56
+ :warning_code => :file_access,
57
+ :message => message,
58
+ :confidence => confidence,
59
+ :code => call,
60
+ :user_input => match
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,35 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckFileDisclosure < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for versions with file existence disclosure vulnerability"
7
+
8
+ def run_check
9
+ fix_version = case
10
+ when version_between?('2.0.0', '2.3.18')
11
+ '3.2.21'
12
+ when version_between?('3.0.0', '3.2.20')
13
+ '3.2.21'
14
+ when version_between?('4.0.0', '4.0.11')
15
+ '4.0.12'
16
+ when version_between?('4.1.0', '4.1.7')
17
+ '4.1.8'
18
+ else
19
+ nil
20
+ end
21
+
22
+ if fix_version and serves_static_assets?
23
+ warn :warning_type => "File Access",
24
+ :warning_code => :CVE_2014_7829,
25
+ :message => "Rails #{rails_version} has a file existence disclosure. Upgrade to #{fix_version} or disable serving static assets",
26
+ :confidence => CONFIDENCE[:high],
27
+ :gem_info => gemfile_or_environment,
28
+ :link_path => "https://groups.google.com/d/msg/rubyonrails-security/23fiuwb1NBA/MQVM1-5GkPMJ"
29
+ end
30
+ end
31
+
32
+ def serves_static_assets?
33
+ true? tracker.config.rails[:serve_static_assets]
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ #Check for filter skipping vulnerability
4
+ #http://groups.google.com/group/rubyonrails-security/browse_thread/thread/3420ac71aed312d6
5
+ class Brakeman::CheckFilterSkipping < Brakeman::BaseCheck
6
+ Brakeman::Checks.add self
7
+
8
+ @description = "Checks for versions 3.0-3.0.9 which had a vulnerability in filters"
9
+
10
+ def run_check
11
+ if version_between?('3.0.0', '3.0.9') and uses_arbitrary_actions?
12
+
13
+ warn :warning_type => "Default Routes",
14
+ :warning_code => :CVE_2011_2929,
15
+ :message => "Versions before 3.0.10 have a vulnerability which allows filters to be bypassed: CVE-2011-2929",
16
+ :confidence => CONFIDENCE[:high],
17
+ :gem_info => gemfile_or_environment,
18
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/NCCsca7TEtY/discussion"
19
+ end
20
+ end
21
+
22
+ def uses_arbitrary_actions?
23
+ tracker.routes.each do |name, actions|
24
+ if actions.include? :allow_all_actions
25
+ return true
26
+ end
27
+ end
28
+
29
+ false
30
+ end
31
+ end
@@ -0,0 +1,74 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ #Checks that +protect_from_forgery+ is set in the ApplicationController.
4
+ #
5
+ #Also warns for CSRF weakness in certain versions of Rails:
6
+ #http://groups.google.com/group/rubyonrails-security/browse_thread/thread/2d95a3cc23e03665
7
+ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
8
+ Brakeman::Checks.add self
9
+
10
+ @description = "Verifies that protect_from_forgery is enabled in ApplicationController"
11
+
12
+ def run_check
13
+ app_controller = tracker.controllers[:ApplicationController]
14
+ return unless app_controller and app_controller.ancestor? :"ActionController::Base"
15
+
16
+ if tracker.config.allow_forgery_protection?
17
+ warn :controller => :ApplicationController,
18
+ :warning_type => "Cross-Site Request Forgery",
19
+ :warning_code => :csrf_protection_disabled,
20
+ :message => "Forgery protection is disabled",
21
+ :confidence => CONFIDENCE[:high],
22
+ :file => app_controller.file
23
+
24
+ elsif app_controller and not app_controller.protect_from_forgery?
25
+
26
+ warn :controller => :ApplicationController,
27
+ :warning_type => "Cross-Site Request Forgery",
28
+ :warning_code => :csrf_protection_missing,
29
+ :message => "'protect_from_forgery' should be called in ApplicationController",
30
+ :confidence => CONFIDENCE[:high],
31
+ :file => app_controller.file,
32
+ :line => app_controller.top_line
33
+
34
+ elsif version_between? "2.1.0", "2.3.10"
35
+
36
+ warn :controller => :ApplicationController,
37
+ :warning_type => "Cross-Site Request Forgery",
38
+ :warning_code => :CVE_2011_0447,
39
+ :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",
40
+ :confidence => CONFIDENCE[:high],
41
+ :gem_info => gemfile_or_environment,
42
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/LZWjzCPgNmU/discussion"
43
+
44
+ elsif version_between? "3.0.0", "3.0.3"
45
+
46
+ warn :controller => :ApplicationController,
47
+ :warning_type => "Cross-Site Request Forgery",
48
+ :warning_code => :CVE_2011_0447,
49
+ :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",
50
+ :confidence => CONFIDENCE[:high],
51
+ :gem_info => gemfile_or_environment,
52
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/LZWjzCPgNmU/discussion"
53
+ elsif version_between? "4.0.0", "100.0.0" and forgery_opts = app_controller.options[:protect_from_forgery]
54
+
55
+ unless forgery_opts.is_a?(Array) and sexp?(forgery_opts.first) and
56
+ access_arg = hash_access(forgery_opts.first.first_arg, :with) and symbol? access_arg and
57
+ access_arg.value == :exception
58
+
59
+ args = {
60
+ :controller => :ApplicationController,
61
+ :warning_type => "Cross-Site Request Forgery",
62
+ :warning_code => :csrf_not_protected_by_raising_exception,
63
+ :message => "protect_from_forgery should be configured with 'with: :exception'",
64
+ :confidence => CONFIDENCE[:med],
65
+ :file => app_controller.file
66
+ }
67
+
68
+ args.merge!(:code => forgery_opts.first) if forgery_opts.is_a?(Array)
69
+
70
+ warn args
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,31 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckHeaderDoS < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for header DoS (CVE-2013-6414)"
7
+
8
+ def run_check
9
+ if (version_between? "3.0.0", "3.2.15" or version_between? "4.0.0", "4.0.1") and not has_workaround?
10
+ message = "Rails #{rails_version} has a denial of service vulnerability (CVE-2013-6414). Upgrade to Rails version "
11
+
12
+ if version_between? "3.0.0", "3.2.15"
13
+ message << "3.2.16"
14
+ else
15
+ message << "4.0.2"
16
+ end
17
+
18
+ warn :warning_type => "Denial of Service",
19
+ :warning_code => :CVE_2013_6414,
20
+ :message => message,
21
+ :confidence => CONFIDENCE[:med],
22
+ :gem_info => gemfile_or_environment,
23
+ :link_path => "https://groups.google.com/d/msg/ruby-security-ann/A-ebV4WxzKg/KNPTbX8XAQUJ"
24
+ end
25
+ end
26
+
27
+ def has_workaround?
28
+ tracker.check_initializers(:ActiveSupport, :on_load).any? and
29
+ tracker.check_initializers(:"ActionView::LookupContext::DetailsKey", :class_eval).any?
30
+ end
31
+ end
@@ -0,0 +1,48 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckI18nXSS < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for i18n XSS (CVE-2013-4491)"
7
+
8
+ def run_check
9
+ if (version_between? "3.0.6", "3.2.15" or version_between? "4.0.0", "4.0.1") and not has_workaround?
10
+ message = "Rails #{rails_version} has an XSS vulnerability in i18n (CVE-2013-4491). Upgrade to Rails version "
11
+ i18n_gem = tracker.config.gem_version :i18n
12
+
13
+ if version_between? "3.0.6", "3.1.99" and version_before i18n_gem, "0.5.1"
14
+ message << "3.2.16 or i18n 0.5.1"
15
+ elsif version_between? "3.2.0", "4.0.1" and version_before i18n_gem, "0.6.6"
16
+ message << "4.0.2 or i18n 0.6.6"
17
+ else
18
+ return
19
+ end
20
+
21
+ warn :warning_type => "Cross Site Scripting",
22
+ :warning_code => :CVE_2013_4491,
23
+ :message => message,
24
+ :confidence => CONFIDENCE[:med],
25
+ :gem_info => gemfile_or_environment(:i18n),
26
+ :link_path => "https://groups.google.com/d/msg/ruby-security-ann/pLrh6DUw998/bLFEyIO4k_EJ"
27
+ end
28
+ end
29
+
30
+ def version_before gem_version, target
31
+ return true unless gem_version
32
+ gem_version.split('.').map(&:to_i).zip(target.split('.').map(&:to_i)).each do |gv, t|
33
+ if gv < t
34
+ return true
35
+ elsif gv > t
36
+ return false
37
+ end
38
+ end
39
+
40
+ false
41
+ end
42
+
43
+ def has_workaround?
44
+ tracker.check_initializers(:I18n, :const_defined?).any? do |match|
45
+ match.last.first_arg == s(:lit, :MissingTranslation)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,38 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckJRubyXML < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for versions with JRuby XML parsing backend"
7
+
8
+ def run_check
9
+ return unless RUBY_PLATFORM == "java"
10
+
11
+ fix_version = case
12
+ when version_between?('3.0.0', '3.0.99')
13
+ '3.2.13'
14
+ when version_between?('3.1.0', '3.1.11')
15
+ '3.1.12'
16
+ when version_between?('3.2.0', '3.2.12')
17
+ '3.2.13'
18
+ else
19
+ return
20
+ end
21
+
22
+ #Check for workaround
23
+ tracker.check_initializers(:"ActiveSupport::XmlMini", :backend=).each do |result|
24
+ arg = result.call.first_arg
25
+
26
+ if string? arg and arg.value == "REXML"
27
+ return
28
+ end
29
+ end
30
+
31
+ warn :warning_type => "File Access",
32
+ :warning_code => :CVE_2013_1856,
33
+ :message => "Rails #{rails_version} with JRuby has a vulnerability in XML parser: upgrade to #{fix_version} or patch",
34
+ :confidence => CONFIDENCE[:high],
35
+ :gem_info => gemfile_or_environment,
36
+ :link => "https://groups.google.com/d/msg/rubyonrails-security/KZwsQbYsOiI/5kUV7dSCJGwJ"
37
+ end
38
+ end
@@ -0,0 +1,47 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckJSONEncoding < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for missing JSON encoding (CVE-2015-3226)"
7
+
8
+ def run_check
9
+ if (version_between? "4.1.0", "4.1.10" or version_between? "4.2.0", "4.2.1") and not has_workaround?
10
+ message = "Rails #{rails_version} does not encode JSON keys (CVE-2015-3226). Upgrade to Rails version "
11
+
12
+ if version_between? "4.1.0", "4.1.10"
13
+ message << "4.1.11"
14
+ else
15
+ message << "4.2.2"
16
+ end
17
+
18
+ if tracker.find_call(:methods => [:to_json, :encode]).any?
19
+ confidence = CONFIDENCE[:high]
20
+ else
21
+ confidence = CONFIDENCE[:med]
22
+ end
23
+
24
+ warn :warning_type => "Cross Site Scripting",
25
+ :warning_code => :CVE_2015_3226,
26
+ :message => message,
27
+ :confidence => confidence,
28
+ :gem_info => gemfile_or_environment,
29
+ :link_path => "https://groups.google.com/d/msg/rubyonrails-security/7VlB_pck3hU/3QZrGIaQW6cJ"
30
+ end
31
+ end
32
+
33
+ def has_workaround?
34
+ workaround = s(:module, :ActiveSupport,
35
+ s(:module, :JSON,
36
+ s(:module, :Encoding,
37
+ s(:call, nil, :private),
38
+ s(:class, :EscapedString, nil,
39
+ s(:defn, :to_s,
40
+ s(:args),
41
+ s(:self))))))
42
+
43
+ tracker.initializers.any? do |name, initializer|
44
+ initializer == workaround
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,107 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckJSONParsing < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for JSON parsing vulnerabilities CVE-2013-0333 and CVE-2013-0269"
7
+
8
+ def run_check
9
+ check_cve_2013_0333
10
+ check_cve_2013_0269
11
+ end
12
+
13
+ def check_cve_2013_0333
14
+ return unless version_between? "0.0.0", "2.3.15" or version_between? "3.0.0", "3.0.19"
15
+
16
+ unless uses_yajl? or uses_gem_backend?
17
+ new_version = if version_between? "0.0.0", "2.3.14"
18
+ "2.3.16"
19
+ elsif version_between? "3.0.0", "3.0.19"
20
+ "3.0.20"
21
+ end
22
+
23
+ message = "Rails #{rails_version} has a serious JSON parsing vulnerability: upgrade to #{new_version} or patch"
24
+ if uses_yajl?
25
+ gem_info = gemfile_or_environment(:yajl)
26
+ else
27
+ gem_info = gemfile_or_environment
28
+ end
29
+
30
+ warn :warning_type => "Remote Code Execution",
31
+ :warning_code => :CVE_2013_0333,
32
+ :message => message,
33
+ :confidence => CONFIDENCE[:high],
34
+ :gem_info => gem_info,
35
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/1h2DR63ViGo/discussion"
36
+ end
37
+ end
38
+
39
+ #Check if `yajl` is included in Gemfile
40
+ def uses_yajl?
41
+ tracker.config.has_gem? :yajl
42
+ end
43
+
44
+ #Check for `ActiveSupport::JSON.backend = "JSONGem"`
45
+ def uses_gem_backend?
46
+ matches = tracker.check_initializers(:'ActiveSupport::JSON', :backend=)
47
+
48
+ unless matches.empty?
49
+ json_gem = s(:str, "JSONGem")
50
+
51
+ matches.each do |result|
52
+ if result.call.first_arg == json_gem
53
+ return true
54
+ end
55
+ end
56
+ end
57
+
58
+ false
59
+ end
60
+
61
+ def check_cve_2013_0269
62
+ [:json, :json_pure].each do |name|
63
+ gem_hash = tracker.config.get_gem name
64
+ check_json_version name, gem_hash[:version] if gem_hash and gem_hash[:version]
65
+ end
66
+ end
67
+
68
+ def check_json_version name, version
69
+ return if version >= "1.7.7" or
70
+ (version >= "1.6.8" and version < "1.7.0") or
71
+ (version >= "1.5.5" and version < "1.6.0")
72
+
73
+ warning_type = "Denial of Service"
74
+ confidence = CONFIDENCE[:med]
75
+ message = "#{name} gem version #{version} has a symbol creation vulnerablity: upgrade to "
76
+
77
+ if version >= "1.7.0"
78
+ confidence = CONFIDENCE[:high]
79
+ warning_type = "Remote Code Execution"
80
+ message = "#{name} gem version #{version} has a remote code vulnerablity: upgrade to 1.7.7"
81
+ elsif version >= "1.6.0"
82
+ message << "1.6.8"
83
+ elsif version >= "1.5.0"
84
+ message << "1.5.5"
85
+ else
86
+ confidence = CONFIDENCE[:low]
87
+ message << "1.5.5"
88
+ end
89
+
90
+ if confidence == CONFIDENCE[:med] and uses_json_parse?
91
+ confidence = CONFIDENCE[:high]
92
+ end
93
+
94
+ warn :warning_type => warning_type,
95
+ :warning_code => :CVE_2013_0269,
96
+ :message => message,
97
+ :confidence => confidence,
98
+ :gem_info => gemfile_or_environment(name),
99
+ :link => "https://groups.google.com/d/topic/rubyonrails-security/4_YvCpLzL58/discussion"
100
+ end
101
+
102
+ def uses_json_parse?
103
+ return @uses_json_parse unless @uses_json_parse.nil?
104
+
105
+ not tracker.find_call(:target => :JSON, :method => :parse).empty?
106
+ end
107
+ end