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