brakeman 1.9.0 → 1.9.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.
data/CHANGES CHANGED
@@ -1,3 +1,15 @@
1
+ # 1.9.1
2
+
3
+ * Update to RubyParser 3.1.1 (neersighted)
4
+ * Remove ActiveSupport dependency (Neil Matatall)
5
+ * Do not warn on arrays passed to `link_to` (Neil Matatall)
6
+ * Warn on secret tokens
7
+ * Warn on more mass assignment methods
8
+ * Add check for CVE-2012-5664
9
+ * Add check for CVE-2013-0155
10
+ * Add check for CVE-2013-0156
11
+ * Add check for unsafe `YAML.load`
12
+
1
13
  # 1.9.0
2
14
 
3
15
  * Update to RubyParser 3
@@ -65,6 +65,10 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
65
65
  # Decided NOT warn on models. polymorphic_path is called it a model is
66
66
  # passed to link_to (which passes it to url_for)
67
67
 
68
+ elsif array? url_arg
69
+ # Just like models, polymorphic path/url is called if the argument is
70
+ # an array
71
+
68
72
  elsif hash? url_arg
69
73
 
70
74
  # url_for uses the key/values pretty carefully and I don't see a risk.
@@ -29,7 +29,13 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
29
29
  :update_attributes!,
30
30
  :create,
31
31
  :create!,
32
- :build]
32
+ :build,
33
+ :first_or_create,
34
+ :first_or_create!,
35
+ :first_or_initialize!,
36
+ :assign_attributes,
37
+ :update
38
+ ]
33
39
 
34
40
  Brakeman.debug "Processing possible mass assignment calls"
35
41
  calls.each do |result|
@@ -79,11 +85,16 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
79
85
  #Want to ignore calls to Model.new that have no arguments
80
86
  def check_call call
81
87
  process_call_args call
82
- first_arg = call.first_arg
83
88
 
84
- if first_arg.nil? #empty new()
89
+ if call.method == :update
90
+ arg = call.second_arg
91
+ else
92
+ arg = call.first_arg
93
+ end
94
+
95
+ if arg.nil? #empty new()
85
96
  false
86
- elsif hash? first_arg and not include_user_input? first_arg
97
+ elsif hash? arg and not include_user_input? arg
87
98
  false
88
99
  elsif all_literal_args? call
89
100
  false
@@ -26,14 +26,27 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
26
26
  if tracker.initializers["session_store.rb"]
27
27
  process tracker.initializers["session_store.rb"]
28
28
  end
29
+
30
+ if tracker.initializers["secret_token.rb"]
31
+ process tracker.initializers["secret_token.rb"]
32
+ end
29
33
  end
30
34
 
31
35
  #Looks for ActionController::Base.session = { ... }
32
36
  #in Rails 2.x apps
37
+ #
38
+ #and App::Application.config.secret_token =
39
+ #in Rails 3.x apps
33
40
  def process_attrasgn exp
34
41
  if not tracker.options[:rails3] and exp.target == @session_settings and exp.method == :session=
35
42
  check_for_issues exp.first_arg, "#{tracker.options[:app_path]}/config/initializers/session_store.rb"
36
43
  end
44
+
45
+ if tracker.options[:rails3] and settings_target?(exp.target) and
46
+ exp.method == :secret_token= and string? exp.first_arg
47
+
48
+ warn_about_secret_token exp, "#{tracker.options[:app_path]}/config/initializers/secret_token.rb"
49
+ end
37
50
 
38
51
  exp
39
52
  end
@@ -69,8 +82,8 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
69
82
  end
70
83
 
71
84
  if value = hash_access(settings, :secret)
72
- if string? value and value.value.length < 30
73
- warn_about_secret_length value, file
85
+ if string? value
86
+ warn_about_secret_token value, file
74
87
  end
75
88
  end
76
89
  end
@@ -101,9 +114,9 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
101
114
 
102
115
  end
103
116
 
104
- def warn_about_secret_length value, file
117
+ def warn_about_secret_token value, file
105
118
  warn :warning_type => "Session Setting",
106
- :message => "Session secret should be at least 30 characters long",
119
+ :message => "Session secret should not be included in version control",
107
120
  :confidence => CONFIDENCE[:high],
108
121
  :line => value.line,
109
122
  :file => file
@@ -46,6 +46,12 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
46
46
  Brakeman.debug "Checking version of Rails for CVE-2012-2695"
47
47
  check_rails_version_for_cve_2012_2695
48
48
 
49
+ Brakeman.debug "Checking version of Rails for CVE-2012-5664"
50
+ check_rails_version_for_cve_2012_5664
51
+
52
+ Brakeman.debug "Checking version of Rails for CVE-2013-0155"
53
+ check_rails_version_for_cve_2013_0155
54
+
49
55
  Brakeman.debug "Processing possible SQL calls"
50
56
  calls.each do |c|
51
57
  process_result c
@@ -121,6 +127,26 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
121
127
  end
122
128
  end
123
129
 
130
+ def check_rails_version_for_cve_2012_5664
131
+ if version_between?("2.0.0", "2.3.14") || version_between?("3.0.0", "3.0.17") || version_between?("3.1.0", "3.1.8") || version_between?("3.2.0", "3.2.9")
132
+ warn :warning_type => 'SQL Injection',
133
+ :message => 'All versions of Rails before 3.0.18, 3.1.9, and 3.2.10 contain a SQL Injection Vulnerability: CVE-2012-5664; Upgrade to 3.2.10, 3.1.9, 3.0.18',
134
+ :confidence => CONFIDENCE[:high],
135
+ :file => gemfile_or_environment,
136
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/DCNTNp_qjFM/discussion"
137
+ end
138
+ end
139
+
140
+ def check_rails_version_for_cve_2013_0155
141
+ if version_between?("2.0.0", "2.3.15") || version_between?("3.0.0", "3.0.18") || version_between?("3.1.0", "3.1.9") || version_between?("3.2.0", "3.2.10")
142
+ warn :warning_type => 'SQL Injection',
143
+ :message => 'All versions of Rails before 3.0.19, 3.1.10, and 3.2.11 contain a SQL Injection Vulnerability: CVE-2013-0155; Upgrade to 3.2.11, 3.1.10, 3.0.19',
144
+ :confidence => CONFIDENCE[:high],
145
+ :file => gemfile_or_environment,
146
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/c7jT-EeN9eI/discussion"
147
+ end
148
+ end
149
+
124
150
  def process_scope_with_block model_name, args
125
151
  scope_name = args[1][1]
126
152
  block = args[-1][-1]
@@ -0,0 +1,51 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ #YAML.load can be used for remote code execution
4
+ class Brakeman::CheckYAMLLoad < Brakeman::BaseCheck
5
+ Brakeman::Checks.add self
6
+
7
+ @description = "Checks for uses of YAML.load"
8
+
9
+ def run_check
10
+ tracker.find_call(:target => :YAML, :method => :load).each do |result|
11
+ check_yaml_load result
12
+ end
13
+ end
14
+
15
+ def check_yaml_load result
16
+ return if duplicate? result
17
+ add_result result
18
+
19
+ arg = result[:call].first_arg
20
+
21
+ if input = has_immediate_user_input?(arg)
22
+ confidence = CONFIDENCE[:high]
23
+ elsif input = include_user_input?(arg)
24
+ confidence = CONFIDENCE[:med]
25
+ end
26
+
27
+ if confidence
28
+ input_type = case input.type
29
+ when :params
30
+ "parameter value"
31
+ when :cookies
32
+ "cookies value"
33
+ when :request
34
+ "request value"
35
+ when :model
36
+ "model attribute"
37
+ else
38
+ "user input"
39
+ end
40
+
41
+ message = "YAML.load called with #{input_type}"
42
+
43
+ warn :result => result,
44
+ :warning_type => "Remote Code Execution",
45
+ :message => message,
46
+ :user_input => input.match,
47
+ :confidence => confidence,
48
+ :link_path => "remote_code_execution_yaml_load"
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,118 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckYAMLParsing < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for YAML parsing vulnerabilities (CVE-2013-0156)"
7
+
8
+ def run_check
9
+ return unless version_between? "0.0.0", "2.3.14" or
10
+ version_between? "3.0.0", "3.0.18" or
11
+ version_between? "3.1.0", "3.1.9" or
12
+ version_between? "3.2.0", "3.2.10"
13
+
14
+ unless disabled_xml_parser? or disabled_xml_dangerous_types?
15
+ new_version = if version_between? "0.0.0", "2.3.14"
16
+ "2.3.15"
17
+ elsif version_between? "3.0.0", "3.0.18"
18
+ "3.0.19"
19
+ elsif version_between? "3.1.0", "3.1.9"
20
+ "3.1.10"
21
+ elsif version_between? "3.2.0", "3.2.10"
22
+ "3.2.11"
23
+ end
24
+
25
+ message = "Rails #{tracker.config[:rails_version]} has a remote code execution vulnerability: upgrade to #{new_version} or disable XML parsing"
26
+
27
+ warn :warning_type => "Remote Code Execution",
28
+ :message => message,
29
+ :confidence => CONFIDENCE[:high],
30
+ :file => gemfile_or_environment,
31
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/61bkgvnSGTQ/discussion"
32
+ end
33
+
34
+ #Warn if app accepts YAML
35
+ if version_between?("0.0.0", "2.3.14") and enabled_yaml_parser?
36
+ message = "Parsing YAML request parameters enables remote code execution: disable YAML parser"
37
+
38
+ warn :warning_type => "Remote Code Execution",
39
+ :message => message,
40
+ :confidence => CONFIDENCE[:high],
41
+ :link_path => "https://groups.google.com/d/topic/rubyonrails-security/61bkgvnSGTQ/discussion"
42
+ end
43
+ end
44
+
45
+ def disabled_xml_parser?
46
+ if version_between? "0.0.0", "2.3.14"
47
+ #Look for ActionController::Base.param_parsers.delete(Mime::XML)
48
+ params_parser = s(:call,
49
+ s(:colon2, s(:const, :ActionController), :Base),
50
+ :param_parsers)
51
+
52
+ matches = tracker.check_initializers(params_parser, :delete)
53
+ else
54
+ #Look for ActionDispatch::ParamsParser::DEFAULT_PARSERS.delete(Mime::XML)
55
+ matches = tracker.check_initializers(:"ActionDispatch::ParamsParser::DEFAULT_PARSERS", :delete)
56
+ end
57
+
58
+ unless matches.empty?
59
+ mime_xml = s(:colon2, s(:const, :Mime), :XML)
60
+
61
+ matches.each do |result|
62
+ if result.call.first_arg == mime_xml
63
+ return true
64
+ end
65
+ end
66
+ end
67
+
68
+ false
69
+ end
70
+
71
+ #Look for ActionController::Base.param_parsers[Mime::YAML] = :yaml
72
+ #in Rails 2.x apps
73
+ def enabled_yaml_parser?
74
+ param_parsers = s(:call,
75
+ s(:colon2, s(:const, :ActionController), :Base),
76
+ :param_parsers)
77
+
78
+ matches = tracker.check_initializers(param_parsers, :[]=)
79
+
80
+ mime_yaml = s(:colon2, s(:const, :Mime), :YAML)
81
+
82
+ matches.each do |result|
83
+ if result.call.first_arg == mime_yaml and
84
+ symbol? result.call.second_arg and
85
+ result.call.second_arg.value == :yaml
86
+
87
+ return true
88
+ end
89
+ end
90
+
91
+ false
92
+ end
93
+
94
+ def disabled_xml_dangerous_types?
95
+ if version_between? "0.0.0", "2.3.14"
96
+ matches = tracker.check_initializers(:"ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING", :delete)
97
+ else
98
+ matches = tracker.check_initializers(:"ActiveSupport::XmlMini::PARSING", :delete)
99
+ end
100
+
101
+ symbols_off = false
102
+ yaml_off = false
103
+
104
+ matches.each do |result|
105
+ arg = result.call.first_arg
106
+
107
+ if string? arg
108
+ if arg.value == "yaml"
109
+ yaml_off = true
110
+ elsif arg.value == "symbol"
111
+ symbols_off = true
112
+ end
113
+ end
114
+ end
115
+
116
+ symbols_off and yaml_off
117
+ end
118
+ end
@@ -146,6 +146,8 @@ class Brakeman::FindCall < Brakeman::BaseProcessor
146
146
  else
147
147
  false
148
148
  end
149
+ when Sexp
150
+ search_terms == item
149
151
  when Enumerable
150
152
  if search_terms.empty?
151
153
  item == nil
@@ -1,5 +1,4 @@
1
1
  require 'set'
2
- require 'active_support/inflector'
3
2
 
4
3
  #This is a mixin containing utility methods.
5
4
  module Brakeman::Util
@@ -40,11 +39,12 @@ module Brakeman::Util
40
39
  downcase
41
40
  end
42
41
 
43
- #Use ActiveSupport::Inflector to pluralize a word.
42
+ # stupid simple, used to delegate to ActiveSupport
44
43
  def pluralize word
45
- ActiveSupport::Inflector.pluralize word
44
+ word + "s"
46
45
  end
47
46
 
47
+
48
48
  #Takes an Sexp like
49
49
  # (:hash, (:lit, :key), (:str, "value"))
50
50
  #and yields the key and value pairs to the given block.
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "1.9.0"
2
+ Version = "1.9.1"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brakeman
3
3
  version: !ruby/object:Gem::Version
4
- hash: 51
4
+ hash: 49
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 9
9
- - 0
10
- version: 1.9.0
9
+ - 1
10
+ version: 1.9.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Justin Collins
@@ -15,56 +15,28 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-12-25 00:00:00 Z
18
+ date: 2013-01-19 00:00:00 Z
19
19
  dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: activesupport
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- version: "0"
32
- type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: i18n
36
- prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
46
- type: :runtime
47
- version_requirements: *id002
48
20
  - !ruby/object:Gem::Dependency
49
21
  name: ruby_parser
50
22
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
52
24
  none: false
53
25
  requirements:
54
26
  - - ~>
55
27
  - !ruby/object:Gem::Version
56
- hash: 15
28
+ hash: 1
57
29
  segments:
58
30
  - 3
59
- - 0
60
- - 4
61
- version: 3.0.4
31
+ - 1
32
+ - 1
33
+ version: 3.1.1
62
34
  type: :runtime
63
- version_requirements: *id003
35
+ version_requirements: *id001
64
36
  - !ruby/object:Gem::Dependency
65
37
  name: ruby2ruby
66
38
  prerelease: false
67
- requirement: &id004 !ruby/object:Gem::Requirement
39
+ requirement: &id002 !ruby/object:Gem::Requirement
68
40
  none: false
69
41
  requirements:
70
42
  - - ~>
@@ -75,11 +47,11 @@ dependencies:
75
47
  - 0
76
48
  version: "2.0"
77
49
  type: :runtime
78
- version_requirements: *id004
50
+ version_requirements: *id002
79
51
  - !ruby/object:Gem::Dependency
80
52
  name: terminal-table
81
53
  prerelease: false
82
- requirement: &id005 !ruby/object:Gem::Requirement
54
+ requirement: &id003 !ruby/object:Gem::Requirement
83
55
  none: false
84
56
  requirements:
85
57
  - - ~>
@@ -90,11 +62,11 @@ dependencies:
90
62
  - 4
91
63
  version: "1.4"
92
64
  type: :runtime
93
- version_requirements: *id005
65
+ version_requirements: *id003
94
66
  - !ruby/object:Gem::Dependency
95
67
  name: fastercsv
96
68
  prerelease: false
97
- requirement: &id006 !ruby/object:Gem::Requirement
69
+ requirement: &id004 !ruby/object:Gem::Requirement
98
70
  none: false
99
71
  requirements:
100
72
  - - ~>
@@ -105,11 +77,11 @@ dependencies:
105
77
  - 5
106
78
  version: "1.5"
107
79
  type: :runtime
108
- version_requirements: *id006
80
+ version_requirements: *id004
109
81
  - !ruby/object:Gem::Dependency
110
82
  name: highline
111
83
  prerelease: false
112
- requirement: &id007 !ruby/object:Gem::Requirement
84
+ requirement: &id005 !ruby/object:Gem::Requirement
113
85
  none: false
114
86
  requirements:
115
87
  - - ~>
@@ -120,11 +92,11 @@ dependencies:
120
92
  - 6
121
93
  version: "1.6"
122
94
  type: :runtime
123
- version_requirements: *id007
95
+ version_requirements: *id005
124
96
  - !ruby/object:Gem::Dependency
125
97
  name: erubis
126
98
  prerelease: false
127
- requirement: &id008 !ruby/object:Gem::Requirement
99
+ requirement: &id006 !ruby/object:Gem::Requirement
128
100
  none: false
129
101
  requirements:
130
102
  - - ~>
@@ -135,11 +107,11 @@ dependencies:
135
107
  - 6
136
108
  version: "2.6"
137
109
  type: :runtime
138
- version_requirements: *id008
110
+ version_requirements: *id006
139
111
  - !ruby/object:Gem::Dependency
140
112
  name: haml
141
113
  prerelease: false
142
- requirement: &id009 !ruby/object:Gem::Requirement
114
+ requirement: &id007 !ruby/object:Gem::Requirement
143
115
  none: false
144
116
  requirements:
145
117
  - - ~>
@@ -150,11 +122,11 @@ dependencies:
150
122
  - 0
151
123
  version: "3.0"
152
124
  type: :runtime
153
- version_requirements: *id009
125
+ version_requirements: *id007
154
126
  - !ruby/object:Gem::Dependency
155
127
  name: sass
156
128
  prerelease: false
157
- requirement: &id010 !ruby/object:Gem::Requirement
129
+ requirement: &id008 !ruby/object:Gem::Requirement
158
130
  none: false
159
131
  requirements:
160
132
  - - ~>
@@ -165,11 +137,11 @@ dependencies:
165
137
  - 0
166
138
  version: "3.0"
167
139
  type: :runtime
168
- version_requirements: *id010
140
+ version_requirements: *id008
169
141
  - !ruby/object:Gem::Dependency
170
142
  name: multi_json
171
143
  prerelease: false
172
- requirement: &id011 !ruby/object:Gem::Requirement
144
+ requirement: &id009 !ruby/object:Gem::Requirement
173
145
  none: false
174
146
  requirements:
175
147
  - - ~>
@@ -180,7 +152,7 @@ dependencies:
180
152
  - 3
181
153
  version: "1.3"
182
154
  type: :runtime
183
- version_requirements: *id011
155
+ version_requirements: *id009
184
156
  description: Brakeman detects security vulnerabilities in Ruby on Rails applications via static analysis.
185
157
  email:
186
158
  executables:
@@ -215,6 +187,7 @@ files:
215
187
  - lib/brakeman/checks/check_session_settings.rb
216
188
  - lib/brakeman/checks/check_model_attributes.rb
217
189
  - lib/brakeman/checks/check_redirect.rb
190
+ - lib/brakeman/checks/check_yaml_parsing.rb
218
191
  - lib/brakeman/checks/check_skip_before_filter.rb
219
192
  - lib/brakeman/checks/check_response_splitting.rb
220
193
  - lib/brakeman/checks/check_mail_to.rb
@@ -234,6 +207,7 @@ files:
234
207
  - lib/brakeman/checks/check_execute.rb
235
208
  - lib/brakeman/checks/check_translate_bug.rb
236
209
  - lib/brakeman/checks/check_default_routes.rb
210
+ - lib/brakeman/checks/check_yaml_load.rb
237
211
  - lib/brakeman/checks/check_link_to.rb
238
212
  - lib/brakeman/checks/check_quote_table_name.rb
239
213
  - lib/brakeman/checks/check_send.rb