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,101 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckSQLCVEs < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for several SQL CVEs"
7
+
8
+ def run_check
9
+ check_rails_versions_against_cve_issues
10
+ check_cve_2014_0080
11
+ end
12
+
13
+ def check_rails_versions_against_cve_issues
14
+ issues = [
15
+ {
16
+ :cve => "CVE-2012-2660",
17
+ :versions => [%w[2.0.0 2.3.14 2.3.17], %w[3.0.0 3.0.12 3.0.13], %w[3.1.0 3.1.4 3.1.5], %w[3.2.0 3.2.3 3.2.4]],
18
+ :url => "https://groups.google.com/d/topic/rubyonrails-security/8SA-M3as7A8/discussion"
19
+ },
20
+ {
21
+ :cve => "CVE-2012-2661",
22
+ :versions => [%w[3.0.0 3.0.12 3.0.13], %w[3.1.0 3.1.4 3.1.5], %w[3.2.0 3.2.3 3.2.5]],
23
+ :url => "https://groups.google.com/d/topic/rubyonrails-security/dUaiOOGWL1k/discussion"
24
+ },
25
+ {
26
+ :cve => "CVE-2012-2695",
27
+ :versions => [%w[2.0.0 2.3.14 2.3.15], %w[3.0.0 3.0.13 3.0.14], %w[3.1.0 3.1.5 3.1.6], %w[3.2.0 3.2.5 3.2.6]],
28
+ :url => "https://groups.google.com/d/topic/rubyonrails-security/l4L0TEVAz1k/discussion"
29
+ },
30
+ {
31
+ :cve => "CVE-2012-5664",
32
+ :versions => [%w[2.0.0 2.3.14 2.3.15], %w[3.0.0 3.0.17 3.0.18], %w[3.1.0 3.1.8 3.1.9], %w[3.2.0 3.2.9 3.2.18]],
33
+ :url => "https://groups.google.com/d/topic/rubyonrails-security/DCNTNp_qjFM/discussion"
34
+ },
35
+ {
36
+ :cve => "CVE-2013-0155",
37
+ :versions => [%w[2.0.0 2.3.15 2.3.16], %w[3.0.0 3.0.18 3.0.19], %w[3.1.0 3.1.9 3.1.10], %w[3.2.0 3.2.10 3.2.11]],
38
+ :url => "https://groups.google.com/d/topic/rubyonrails-security/c7jT-EeN9eI/discussion"
39
+ },
40
+
41
+ ]
42
+
43
+ unless lts_version? '2.3.18.6'
44
+ issues << {
45
+ :cve => "CVE-2013-6417",
46
+ :versions => [%w[2.0.0 3.2.15 3.2.16], %w[4.0.0 4.0.1 4.0.2]],
47
+ :url => "https://groups.google.com/d/msg/ruby-security-ann/niK4drpSHT4/g8JW8ZsayRkJ"
48
+ }
49
+ end
50
+
51
+ if tracker.config.has_gem? :pg
52
+ issues << {
53
+ :cve => "CVE-2014-3482",
54
+ :versions => [%w[2.0.0 2.9.9 3.2.19], %w[3.0.0 3.2.18 3.2.19], %w[4.0.0 4.0.6 4.0.7], %w[4.1.0 4.1.2 4.1.3]],
55
+ :url => "https://groups.google.com/d/msg/rubyonrails-security/wDxePLJGZdI/WP7EasCJTA4J"
56
+ } <<
57
+ {
58
+ :cve => "CVE-2014-3483",
59
+ :versions => [%w[2.0.0 2.9.9 3.2.19], %w[3.0.0 3.2.18 3.2.19], %w[4.0.0 4.0.6 4.0.7], %w[4.1.0 4.1.2 4.1.3]],
60
+ :url => "https://groups.google.com/d/msg/rubyonrails-security/wDxePLJGZdI/WP7EasCJTA4J" }
61
+ end
62
+
63
+ issues.each do |cve_issue|
64
+ cve_warning_for cve_issue[:versions], cve_issue[:cve], cve_issue[:url]
65
+ end
66
+ end
67
+
68
+ def cve_warning_for versions, cve, link
69
+ upgrade_version = upgrade_version? versions
70
+ return unless upgrade_version
71
+
72
+ code = cve.tr('-', '_').to_sym
73
+
74
+ warn :warning_type => 'SQL Injection',
75
+ :warning_code => code,
76
+ :message => "Rails #{rails_version} contains a SQL injection vulnerability (#{cve}). Upgrade to #{upgrade_version}",
77
+ :confidence => CONFIDENCE[:high],
78
+ :gem_info => gemfile_or_environment,
79
+ :link_path => link
80
+ end
81
+
82
+ def upgrade_version? versions
83
+ versions.each do |low, high, upgrade|
84
+ return upgrade if version_between? low, high
85
+ end
86
+
87
+ false
88
+ end
89
+
90
+ def check_cve_2014_0080
91
+ return unless version_between? "4.0.0", "4.0.2" and
92
+ @tracker.config.has_gem? :pg
93
+
94
+ warn :warning_type => 'SQL Injection',
95
+ :warning_code => :CVE_2014_0080,
96
+ :message => "Rails #{rails_version} contains a SQL injection vulnerability (CVE-2014-0080) with PostgreSQL. Upgrade to 4.0.3",
97
+ :confidence => CONFIDENCE[:high],
98
+ :gem_info => gemfile_or_environment(:pg),
99
+ :link_path => "https://groups.google.com/d/msg/rubyonrails-security/Wu96YkTUR6s/pPLBMZrlwvYJ"
100
+ end
101
+ end
@@ -0,0 +1,49 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ # Checks if verify_mode= is called with OpenSSL::SSL::VERIFY_NONE
4
+
5
+ class Brakeman::CheckSSLVerify < Brakeman::BaseCheck
6
+ Brakeman::Checks.add self
7
+
8
+ SSL_VERIFY_NONE = s(:colon2, s(:colon2, s(:const, :OpenSSL), :SSL), :VERIFY_NONE)
9
+
10
+ @description = "Checks for OpenSSL::SSL::VERIFY_NONE"
11
+
12
+ def run_check
13
+ check_open_ssl_verify_none
14
+ check_http_start
15
+ end
16
+
17
+ def check_open_ssl_verify_none
18
+ tracker.find_call(:method => :verify_mode=).each {|call| process_verify_mode_result(call) }
19
+ end
20
+
21
+ def process_verify_mode_result result
22
+ if result[:call].last_arg == SSL_VERIFY_NONE
23
+ warn_about_ssl_verification_bypass result
24
+ end
25
+ end
26
+
27
+ def check_http_start
28
+ tracker.find_call(:target => :'Net::HTTP', :method => :start).each { |call| process_http_start_result call }
29
+ end
30
+
31
+ def process_http_start_result result
32
+ arg = result[:call].last_arg
33
+
34
+ if hash? arg and hash_access(arg, :verify_mode) == SSL_VERIFY_NONE
35
+ warn_about_ssl_verification_bypass result
36
+ end
37
+ end
38
+
39
+ def warn_about_ssl_verification_bypass result
40
+ return if duplicate?(result)
41
+ add_result result
42
+
43
+ warn :result => result,
44
+ :warning_type => "SSL Verification Bypass",
45
+ :warning_code => :ssl_verification_bypass,
46
+ :message => "SSL certificate verification was bypassed",
47
+ :confidence => CONFIDENCE[:high]
48
+ end
49
+ end
@@ -0,0 +1,89 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ #Check for uses of strip_tags in Rails versions before 3.0.17, 3.1.8, 3.2.8 (including 2.3.x):
4
+ #https://groups.google.com/d/topic/rubyonrails-security/FgVEtBajcTY/discussion
5
+ #
6
+ #Check for uses of strip_tags in Rails versions before 2.3.13 and 3.0.10:
7
+ #http://groups.google.com/group/rubyonrails-security/browse_thread/thread/2b9130749b74ea12
8
+ #
9
+ #Check for user of strip_tags with rails-html-sanitizer 1.0.2:
10
+ #https://groups.google.com/d/msg/rubyonrails-security/OU9ugTZcbjc/PjEP46pbFQAJ
11
+ class Brakeman::CheckStripTags < Brakeman::BaseCheck
12
+ Brakeman::Checks.add self
13
+
14
+ @description = "Report strip_tags vulnerabilities"
15
+
16
+ def run_check
17
+ if uses_strip_tags?
18
+ cve_2011_2931
19
+ cve_2012_3465
20
+ end
21
+
22
+ cve_2015_7579
23
+ end
24
+
25
+ def cve_2011_2931
26
+ if version_between?('2.0.0', '2.3.12') or version_between?('3.0.0', '3.0.9')
27
+ if rails_version =~ /^3/
28
+ message = "Versions before 3.0.10 have a vulnerability in strip_tags (CVE-2011-2931)"
29
+ else
30
+ message = "Versions before 2.3.13 have a vulnerability in strip_tags (CVE-2011-2931)"
31
+ end
32
+
33
+ warn :warning_type => "Cross Site Scripting",
34
+ :warning_code => :CVE_2011_2931,
35
+ :message => message,
36
+ :gem_info => gemfile_or_environment,
37
+ :confidence => CONFIDENCE[:high],
38
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/K5EwdJt06hI/discussion"
39
+ end
40
+ end
41
+
42
+ def cve_2012_3465
43
+ case
44
+ when (version_between?('2.0.0', '2.3.14') and tracker.config.escape_html?)
45
+ message = "All Rails 2.x versions have a vulnerability in strip_tags (CVE-2012-3465)"
46
+ when version_between?('3.0.10', '3.0.16')
47
+ message = "Rails #{rails_version} has a vulnerability in strip_tags (CVE-2012-3465). Upgrade to 3.0.17"
48
+ when version_between?('3.1.0', '3.1.7')
49
+ message = "Rails #{rails_version} has a vulnerability in strip_tags (CVE-2012-3465). Upgrade to 3.1.8"
50
+ when version_between?('3.2.0', '3.2.7')
51
+ message = "Rails #{rails_version} has a vulnerability in strip_tags (CVE-2012-3465). Upgrade to 3.2.8"
52
+ else
53
+ return
54
+ end
55
+
56
+ warn :warning_type => "Cross Site Scripting",
57
+ :warning_code => :CVE_2012_3465,
58
+ :message => message,
59
+ :confidence => CONFIDENCE[:high],
60
+ :gem_info => gemfile_or_environment,
61
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/FgVEtBajcTY/discussion"
62
+ end
63
+
64
+ def cve_2015_7579
65
+ if tracker.config.gem_version(:'rails-html-sanitizer') == '1.0.2'
66
+ if uses_strip_tags?
67
+ confidence = CONFIDENCE[:high]
68
+ else
69
+ confidence = CONFIDENCE[:med]
70
+ end
71
+
72
+ message = "rails-html-sanitizer 1.0.2 is vulnerable (CVE-2015-7579). Upgrade to 1.0.3"
73
+
74
+ warn :warning_type => "Cross Site Scripting",
75
+ :warning_code => :CVE_2015_7579,
76
+ :message => message,
77
+ :confidence => confidence,
78
+ :gem_info => gemfile_or_environment,
79
+ :link_path => "https://groups.google.com/d/msg/rubyonrails-security/OU9ugTZcbjc/PjEP46pbFQAJ"
80
+
81
+ end
82
+ end
83
+
84
+ def uses_strip_tags?
85
+ Brakeman.debug "Finding calls to strip_tags()"
86
+
87
+ not tracker.find_call(:target => false, :method => :strip_tags, :nested => true).empty?
88
+ end
89
+ end
@@ -0,0 +1,64 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckSymbolDoS < Brakeman::BaseCheck
4
+ Brakeman::Checks.add_optional self
5
+
6
+ UNSAFE_METHODS = [:to_sym, :literal_to_sym, :intern, :symbolize_keys, :symbolize_keys!]
7
+
8
+ @description = "Checks for symbol denial of service"
9
+
10
+ def run_check
11
+ return if rails_version > "5.0.0"
12
+
13
+ tracker.find_call(:methods => UNSAFE_METHODS, :nested => true).each do |result|
14
+ check_unsafe_symbol_creation(result)
15
+ end
16
+ end
17
+
18
+ def check_unsafe_symbol_creation result
19
+ return if duplicate? result or result[:call].original_line
20
+
21
+ add_result result
22
+
23
+ call = result[:call]
24
+
25
+ if result[:method] == :literal_to_sym
26
+ args = call.select { |e| sexp? e }
27
+ else
28
+ args = [call.target]
29
+ end
30
+
31
+ if input = args.map{ |arg| has_immediate_user_input?(arg) }.compact.first
32
+ confidence = CONFIDENCE[:high]
33
+ elsif input = args.map{ |arg| include_user_input?(arg) }.compact.first
34
+ confidence = CONFIDENCE[:med]
35
+ end
36
+
37
+ if confidence
38
+ return if safe_parameter? input.match
39
+
40
+ message = "Symbol conversion from unsafe string (#{friendly_type_of input})"
41
+
42
+ warn :result => result,
43
+ :warning_type => "Denial of Service",
44
+ :warning_code => :unsafe_symbol_creation,
45
+ :message => message,
46
+ :user_input => input,
47
+ :confidence => confidence
48
+ end
49
+ end
50
+
51
+ def safe_parameter? input
52
+ if call? input
53
+ if node_type? input.target, :params
54
+ input.method == :[] and
55
+ symbol? input.first_arg and
56
+ [:controller, :action].include? input.first_arg.value
57
+ else
58
+ safe_parameter? input.target
59
+ end
60
+ else
61
+ false
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,30 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckSymbolDoSCVE < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for versions with ActiveRecord symbol denial of service vulnerability"
7
+
8
+ def run_check
9
+ fix_version = case
10
+ when version_between?('2.0.0', '2.3.17')
11
+ '2.3.18'
12
+ when version_between?('3.1.0', '3.1.11')
13
+ '3.1.12'
14
+ when version_between?('3.2.0', '3.2.12')
15
+ '3.2.13'
16
+ else
17
+ nil
18
+ end
19
+
20
+ if fix_version && active_record_models.any?
21
+ warn :warning_type => "Denial of Service",
22
+ :warning_code => :CVE_2013_1854,
23
+ :message => "Rails #{rails_version} has a denial of service vulnerability in ActiveRecord: upgrade to #{fix_version} or patch",
24
+ :confidence => CONFIDENCE[:med],
25
+ :gem_info => gemfile_or_environment,
26
+ :link => "https://groups.google.com/d/msg/rubyonrails-security/jgJ4cjjS8FE/BGbHRxnDRTIJ"
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,45 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ #Check for vulnerability in translate() helper that allows cross-site scripting
4
+ class Brakeman::CheckTranslateBug < Brakeman::BaseCheck
5
+ Brakeman::Checks.add self
6
+
7
+ @description = "Report XSS vulnerability in translate helper"
8
+
9
+ def run_check
10
+ return if lts_version? '2.3.18.6'
11
+ if (version_between?('2.3.0', '2.3.99') and tracker.config.escape_html?) or
12
+ version_between?('3.0.0', '3.0.10') or
13
+ version_between?('3.1.0', '3.1.1')
14
+
15
+ confidence = if uses_translate?
16
+ CONFIDENCE[:high]
17
+ else
18
+ CONFIDENCE[:med]
19
+ end
20
+
21
+ description = "have a vulnerability in the translate helper with keys ending in _html"
22
+
23
+ message = if rails_version =~ /^3\.1/
24
+ "Versions before 3.1.2 #{description}."
25
+ elsif rails_version =~ /^3\.0/
26
+ "Versions before 3.0.11 #{description}."
27
+ else
28
+ "Rails 2.3.x using the rails_xss plugin #{description}."
29
+ end
30
+
31
+ warn :warning_type => "Cross Site Scripting",
32
+ :warning_code => :translate_vuln,
33
+ :message => message,
34
+ :confidence => confidence,
35
+ :gem_info => gemfile_or_environment,
36
+ :link_path => "http://groups.google.com/group/rubyonrails-security/browse_thread/thread/2b61d70fb73c7cc5"
37
+ end
38
+ end
39
+
40
+ def uses_translate?
41
+ Brakeman.debug "Finding calls to translate() or t()"
42
+
43
+ tracker.find_call(:target => nil, :methods => [:t, :translate]).any?
44
+ end
45
+ end
@@ -0,0 +1,51 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ # Checks for string interpolation and parameters in calls to
4
+ # String#constantize, String#safe_constantize, Module#const_get and Module#qualified_const_get.
5
+ #
6
+ # Exploit examples at: http://blog.conviso.com.br/2013/02/exploiting-unsafe-reflection-in.html
7
+ class Brakeman::CheckUnsafeReflection < Brakeman::BaseCheck
8
+ Brakeman::Checks.add self
9
+
10
+ @description = "Checks for unsafe reflection"
11
+
12
+ def run_check
13
+ reflection_methods = [:constantize, :safe_constantize, :const_get, :qualified_const_get]
14
+
15
+ tracker.find_call(:methods => reflection_methods, :nested => true).each do |result|
16
+ check_unsafe_reflection result
17
+ end
18
+ end
19
+
20
+ def check_unsafe_reflection result
21
+ return if duplicate? result or result[:call].original_line
22
+ add_result result
23
+
24
+ call = result[:call]
25
+ method = call.method
26
+
27
+ case method
28
+ when :constantize, :safe_constantize
29
+ arg = call.target
30
+ else
31
+ arg = call.first_arg
32
+ end
33
+
34
+ if input = has_immediate_user_input?(arg)
35
+ confidence = CONFIDENCE[:high]
36
+ elsif input = include_user_input?(arg)
37
+ confidence = CONFIDENCE[:med]
38
+ end
39
+
40
+ if confidence
41
+ message = "Unsafe reflection method #{method} called with #{friendly_type_of input}"
42
+
43
+ warn :result => result,
44
+ :warning_type => "Remote Code Execution",
45
+ :warning_code => :unsafe_constantize,
46
+ :message => message,
47
+ :user_input => input,
48
+ :confidence => confidence
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,41 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ # Checks for unscoped calls to models' #find and #find_by_id methods.
4
+ class Brakeman::CheckUnscopedFind < Brakeman::BaseCheck
5
+ Brakeman::Checks.add_optional self
6
+
7
+ @description = "Check for unscoped ActiveRecord queries"
8
+
9
+ def run_check
10
+ Brakeman.debug("Finding instances of #find on models with associations")
11
+
12
+ associated_model_names = active_record_models.keys.select do |name|
13
+ active_record_models[name].associations[:belongs_to]
14
+ end
15
+
16
+ calls = tracker.find_call :method => [:find, :find_by_id, :find_by_id!],
17
+ :targets => associated_model_names
18
+
19
+ calls.each do |call|
20
+ process_result call
21
+ end
22
+ end
23
+
24
+ def process_result result
25
+ return if duplicate? result or result[:call].original_line
26
+
27
+ # Not interested unless argument is user controlled.
28
+ inputs = result[:call].args.map { |arg| include_user_input?(arg) }
29
+ return unless input = inputs.compact.first
30
+
31
+ add_result result
32
+
33
+ warn :result => result,
34
+ :warning_type => "Unscoped Find",
35
+ :warning_code => :unscoped_find,
36
+ :message => "Unscoped call to #{result[:target]}##{result[:method]}",
37
+ :code => result[:call],
38
+ :confidence => CONFIDENCE[:low],
39
+ :user_input => input
40
+ end
41
+ end