brakeman-min 3.1.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ae0fcfd4403660ef4d85cfa8c2d96a244be99fdd
4
- data.tar.gz: f0977436b26ae39b6a1c633cf8845d9a56ee46f4
3
+ metadata.gz: 9a5746f5b6e5de3b4fd957cfc02fe75af84c1e86
4
+ data.tar.gz: 42f11453613d1ee18f26e45d7576141f83779e7d
5
5
  SHA512:
6
- metadata.gz: e3fd9cb70054b14ce68cc713d5b7a9737181c5b4250ebf7a8b6786df162e257157e91f956bf8acb95f7d8f838b58fbdeb84095f91b9b70b1870579a8dca45e80
7
- data.tar.gz: b2b90105d3258977ad07465e812208d24aefbfa1901c8fd4ef4c2174cfa2d2e1c6017ade5d06dcb032b5f7fdc5eca2d9227a51f19abd599c9f8c9ba06c9b54d5
6
+ metadata.gz: 78339bdd3a07bf944d4bf09f591810ba94911c3808662b6aa172941e42a859dc7059977283a838311abdc4189808d89c564e4b32832400da31454340abdec43d
7
+ data.tar.gz: 475cce5d63bd14e7bf3c337e55aee915df5c5f5c257a4a5631cb3af75df1bd9eddc0fc70bdbeae49365b7c72db6152a6f39c7bacc8c6826226e60c646ffdf9c9
data/CHANGES CHANGED
@@ -1,3 +1,17 @@
1
+ # 3.1.1
2
+
3
+ * Add optional check for use of MD5 and SHA1
4
+ * Avoid warning when linking to decorated models
5
+ * Add check for user input in session keys
6
+ * Fix chained assignment
7
+ * Treat a.try(&:b) like a.b()
8
+ * Consider j/escape_javascript safe inside HAML JavaScript blocks
9
+ * Better HAML processing of find_and_preserve calls
10
+ * Add more Arel methods to be ignored in SQL
11
+ * Fix absolute paths for Windows (Cody Frederick)
12
+ * Support newer terminal-table releases
13
+ * Allow searching call index methods by regex (Alex Ianus)
14
+
1
15
  # 3.1.0
2
16
 
3
17
  * Add support for gems.rb/gems.locked
@@ -98,9 +98,12 @@ class Brakeman::CallIndex
98
98
  @calls_by_method[call[:method]] ||= []
99
99
  @calls_by_method[call[:method]] << call
100
100
 
101
- unless call[:target].is_a? Sexp
101
+ if not call[:target].is_a? Sexp
102
102
  @calls_by_target[call[:target]] ||= []
103
103
  @calls_by_target[call[:target]] << call
104
+ elsif call[:target].node_type == :params or call[:target].node_type == :session
105
+ @calls_by_target[call[:target].node_type] ||= []
106
+ @calls_by_target[call[:target].node_type] << call
104
107
  end
105
108
  end
106
109
  end
@@ -139,6 +142,8 @@ class Brakeman::CallIndex
139
142
  def calls_by_method method
140
143
  if method.is_a? Array
141
144
  calls_by_methods method
145
+ elsif method.is_a? Regexp
146
+ calls_by_methods_regex method
142
147
  else
143
148
  @calls_by_method[method.to_sym] || []
144
149
  end
@@ -155,6 +160,14 @@ class Brakeman::CallIndex
155
160
  calls
156
161
  end
157
162
 
163
+ def calls_by_methods_regex methods_regex
164
+ calls = []
165
+ @calls_by_method.each do |key, value|
166
+ calls.concat value if key.to_s.match methods_regex
167
+ end
168
+ calls
169
+ end
170
+
158
171
  def calls_with_no_target
159
172
  @calls_by_target[nil] || []
160
173
  end
@@ -91,6 +91,15 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
91
91
  end
92
92
  end
93
93
 
94
+ def ignore_call? target, method
95
+ decorated_model? method or super
96
+ end
97
+
98
+ def decorated_model? method
99
+ tracker.config.has_gem? :draper and
100
+ method == :decorate
101
+ end
102
+
94
103
  def ignored_method? target, method
95
104
  @ignore_methods.include? method or
96
105
  method.to_s =~ /_path$/ or
@@ -0,0 +1,36 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckSessionManipulation < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Check for user input in session keys"
7
+
8
+ def run_check
9
+ tracker.find_call(:method => :[]=, :target => :session).each do |result|
10
+ process_result result
11
+ end
12
+ end
13
+
14
+ def process_result result
15
+ return if duplicate? result or result[:call].original_line
16
+ add_result result
17
+
18
+ index = result[:call].first_arg
19
+
20
+ if input = has_immediate_user_input?(index)
21
+ if params? index
22
+ confidence = CONFIDENCE[:high]
23
+ else
24
+ confidence = CONFIDENCE[:med]
25
+ end
26
+
27
+ warn :result => result,
28
+ :warning_type => "Session Manipulation",
29
+ :warning_code => :session_key_manipulation,
30
+ :message => "#{friendly_type_of(input).capitalize} used as key in session hash",
31
+ :code => result[:call],
32
+ :user_input => input.match,
33
+ :confidence => confidence
34
+ end
35
+ end
36
+ end
@@ -585,7 +585,9 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
585
585
  end
586
586
  end
587
587
 
588
- AREL_METHODS = [:not, :and, :or, :exists, :join_sources, :arel_table, :gt, :lt, :on, :eq, :eq_any, :where]
588
+ AREL_METHODS = [:all, :and, :arel_table, :as, :eq, :eq_any, :exists, :group,
589
+ :gt, :gteq, :having, :in, :join_sources, :limit, :lt, :lteq, :not,
590
+ :not_eq, :on, :or, :order, :project, :skip, :take, :where, :with]
589
591
 
590
592
  def arel? exp
591
593
  call? exp and (AREL_METHODS.include? exp.method or arel? exp.target)
@@ -0,0 +1,152 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckWeakHash < Brakeman::BaseCheck
4
+ Brakeman::Checks.add_optional self
5
+
6
+ @description = "Checks for use of weak hashes like MD5"
7
+
8
+ DIGEST_CALLS = [:base64digest, :digest, :hexdigest, :new]
9
+
10
+ def run_check
11
+ tracker.find_call(:targets => [:'Digest::MD5', :'Digest::SHA1', :'OpenSSL::Digest::MD5', :'OpenSSL::Digest::SHA1'], :nested => true).each do |result|
12
+ process_hash_result result
13
+ end
14
+
15
+ tracker.find_call(:target => :'Digest::HMAC', :methods => [:new, :hexdigest], :nested => true).each do |result|
16
+ process_hmac_result result
17
+ end
18
+
19
+ tracker.find_call(:targets => [:'OpenSSL::Digest::Digest', :'OpenSSL::Digest'], :method => :new).each do |result|
20
+ process_openssl_result result
21
+ end
22
+ end
23
+
24
+ def process_hash_result result
25
+ return if duplicate? result
26
+ add_result result
27
+
28
+ input = nil
29
+ call = result[:call]
30
+
31
+ if DIGEST_CALLS.include? call.method
32
+ if input = user_input_as_arg?(call)
33
+ input = input.match
34
+ confidence = CONFIDENCE[:high]
35
+ elsif input = hashing_password?(call)
36
+ confidence = CONFIDENCE[:high]
37
+ else
38
+ confidence = CONFIDENCE[:med]
39
+ end
40
+ else
41
+ confidence = CONFIDENCE[:med]
42
+ end
43
+
44
+
45
+ alg = case call.target.last
46
+ when :MD5
47
+ " (MD5)"
48
+ when :SHA1
49
+ " (SHA1)"
50
+ else
51
+ ""
52
+ end
53
+
54
+ warn :result => result,
55
+ :warning_type => "Weak Hash",
56
+ :warning_code => :weak_hash_digest,
57
+ :message => "Weak hashing algorithm#{alg} used",
58
+ :confidence => confidence,
59
+ :user_input => input
60
+ end
61
+
62
+ def process_hmac_result result
63
+ return if duplicate? result
64
+ add_result result
65
+
66
+ call = result[:call]
67
+
68
+ alg = case call.third_arg.last
69
+ when :MD5
70
+ 'MD5'
71
+ when :SHA1
72
+ 'SHA1'
73
+ else
74
+ return
75
+ end
76
+
77
+ warn :result => result,
78
+ :warning_type => "Weak Hash",
79
+ :warning_code => :weak_hash_hmac,
80
+ :message => "Weak hashing algorithm (#{alg}) used in HMAC",
81
+ :confidence => CONFIDENCE[:med]
82
+ end
83
+
84
+ def process_openssl_result result
85
+ return if duplicate? result
86
+ add_result result
87
+
88
+ arg = result[:call].first_arg
89
+
90
+ if string? arg
91
+ alg = arg.value.upcase
92
+
93
+ if alg == 'MD5' or alg == 'SHA1'
94
+ warn :result => result,
95
+ :warning_type => "Weak Hash",
96
+ :warning_code => :weak_hash_digest,
97
+ :message => "Weak hashing algorithm (#{alg}) used",
98
+ :confidence => CONFIDENCE[:med]
99
+ end
100
+ end
101
+ end
102
+
103
+ def user_input_as_arg? call
104
+ call.each_arg do |arg|
105
+ if input = include_user_input?(arg)
106
+ return input
107
+ end
108
+ end
109
+
110
+ nil
111
+ end
112
+
113
+ def hashing_password? call
114
+ call.each_arg do |arg|
115
+ @has_password = false
116
+
117
+ process arg
118
+
119
+ if @has_password
120
+ return @has_password
121
+ end
122
+ end
123
+
124
+ nil
125
+ end
126
+
127
+ def process_call exp
128
+ if exp.method == :password
129
+ @has_password = exp
130
+ else
131
+ process_default exp
132
+ end
133
+
134
+ exp
135
+ end
136
+
137
+ def process_ivar exp
138
+ if exp.value == :@password
139
+ @has_password = exp
140
+ end
141
+
142
+ exp
143
+ end
144
+
145
+ def process_lvar exp
146
+ if exp.value == :password
147
+ @has_password = exp
148
+ end
149
+
150
+ exp
151
+ end
152
+ end
@@ -274,6 +274,15 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
274
274
  exp
275
275
  end
276
276
 
277
+ # Handles x = y = z = 1
278
+ def get_rhs exp
279
+ if node_type? exp, :lasgn, :iasgn, :gasgn, :attrasgn, :cvdecl, :cdecl
280
+ get_rhs(exp.rhs)
281
+ else
282
+ exp
283
+ end
284
+ end
285
+
277
286
  #Local assignment
278
287
  # x = 1
279
288
  def process_lasgn exp
@@ -285,9 +294,9 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
285
294
 
286
295
  if self_assign
287
296
  # Skip branching
288
- env[local] = exp.rhs
297
+ env[local] = get_rhs(exp)
289
298
  else
290
- set_value local, exp.rhs
299
+ set_value local, get_rhs(exp)
291
300
  end
292
301
 
293
302
  exp
@@ -302,12 +311,12 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
302
311
 
303
312
  if self_assign
304
313
  if env[ivar].nil? and @meth_env
305
- @meth_env[ivar] = exp.rhs
314
+ @meth_env[ivar] = get_rhs(exp)
306
315
  else
307
- env[ivar] = exp.rhs
316
+ env[ivar] = get_rhs(exp)
308
317
  end
309
318
  else
310
- set_value ivar, exp.rhs
319
+ set_value ivar, get_rhs(exp)
311
320
  end
312
321
 
313
322
  exp
@@ -317,7 +326,8 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
317
326
  # $x = 1
318
327
  def process_gasgn exp
319
328
  match = Sexp.new(:gvar, exp.lhs)
320
- value = exp.rhs = process(exp.rhs)
329
+ exp.rhs = process(exp.rhs)
330
+ value = get_rhs(exp)
321
331
  value.line = exp.line
322
332
 
323
333
  set_value match, value
@@ -329,7 +339,8 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
329
339
  # @@x = 1
330
340
  def process_cvdecl exp
331
341
  match = Sexp.new(:cvar, exp.lhs)
332
- value = exp.rhs = process(exp.rhs)
342
+ exp.rhs = process(exp.rhs)
343
+ value = get_rhs(exp)
333
344
 
334
345
  set_value match, value
335
346
 
@@ -358,7 +369,8 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
358
369
  env[tar_variable] = hash_insert target.deep_clone, index, value
359
370
  end
360
371
  elsif method.to_s[-1,1] == "="
361
- value = exp.first_arg = process(index_arg)
372
+ exp.first_arg = process(index_arg)
373
+ value = get_rhs(exp)
362
374
  #This is what we'll replace with the value
363
375
  match = Sexp.new(:call, target, method.to_s[0..-2].to_sym)
364
376
 
@@ -478,7 +490,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
478
490
  match = exp.lhs
479
491
  end
480
492
 
481
- env[match] = exp.rhs
493
+ env[match] = get_rhs(exp)
482
494
 
483
495
  exp
484
496
  end
@@ -634,6 +646,11 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
634
646
 
635
647
  # Change x.send(:y, 1) to x.y(1)
636
648
  def collapse_send_call exp, first_arg
649
+ # Handle try(&:id)
650
+ if node_type? first_arg, :block_pass
651
+ first_arg = first_arg[1]
652
+ end
653
+
637
654
  return unless symbol? first_arg or string? first_arg
638
655
  exp.method = first_arg.value.to_sym
639
656
  args = exp.args
@@ -4,7 +4,8 @@ require 'brakeman/processors/template_processor'
4
4
  class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
5
5
  HAML_FORMAT_METHOD = /format_script_(true|false)_(true|false)_(true|false)_(true|false)_(true|false)_(true|false)_(true|false)/
6
6
  HAML_HELPERS = s(:colon2, s(:const, :Haml), :Helpers)
7
-
7
+ JAVASCRIPT_FILTER = s(:colon2, s(:colon2, s(:const, :Haml), :Filters), :Javascript)
8
+
8
9
  #Processes call, looking for template output
9
10
  def process_call exp
10
11
  target = exp.target
@@ -36,20 +37,31 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
36
37
  if string? out
37
38
  ignore
38
39
  else
39
- case method.to_s
40
- when "push_text"
41
- build_output_from_push_text(out)
42
- when HAML_FORMAT_METHOD
43
- if $4 == "true"
44
- Sexp.new :format_escaped, out
45
- else
46
- Sexp.new :format, out
47
- end
48
- else
49
- raise "Unrecognized action on _hamlout: #{method}"
50
- end
51
- end
40
+ r = case method.to_s
41
+ when "push_text"
42
+ build_output_from_push_text(out)
43
+ when HAML_FORMAT_METHOD
44
+ if $4 == "true"
45
+ if string_interp? out
46
+ build_output_from_push_text(out, :escaped_output)
47
+ else
48
+ Sexp.new :format_escaped, out
49
+ end
50
+ else
51
+ if string_interp? out
52
+ build_output_from_push_text(out)
53
+ else
54
+ Sexp.new :format, out
55
+ end
56
+ end
52
57
 
58
+ else
59
+ raise "Unrecognized action on _hamlout: #{method}"
60
+ end
61
+
62
+ @javascript = false
63
+ r
64
+ end
53
65
  end
54
66
 
55
67
  res.line(exp.line)
@@ -75,6 +87,14 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
75
87
  #Process call to render()
76
88
  exp.arglist = process exp.arglist
77
89
  make_render_in_view exp
90
+ elsif target == nil and method == :find_and_preserve
91
+ process exp.first_arg
92
+ elsif method == :render_with_options
93
+ if target == JAVASCRIPT_FILTER
94
+ @javascript = true
95
+ end
96
+
97
+ process exp.first_arg
78
98
  else
79
99
  exp.target = target
80
100
  exp.arglist = process exp.arglist
@@ -117,7 +137,7 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
117
137
 
118
138
  #HAML likes to put interpolated values into _hamlout.push_text
119
139
  #but we want to handle those individually
120
- def build_output_from_push_text exp
140
+ def build_output_from_push_text exp, default = :output
121
141
  if string_interp? exp
122
142
  exp.map! do |e|
123
143
  if sexp? e
@@ -125,7 +145,7 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
125
145
  e = e.value
126
146
  end
127
147
 
128
- get_pushed_value e
148
+ get_pushed_value e, default
129
149
  else
130
150
  e
131
151
  end
@@ -134,9 +154,9 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
134
154
  end
135
155
 
136
156
  #Gets outputs from values interpolated into _hamlout.push_text
137
- def get_pushed_value exp
157
+ def get_pushed_value exp, default = :output
138
158
  return exp unless sexp? exp
139
-
159
+
140
160
  case exp.node_type
141
161
  when :format
142
162
  exp.node_type = :output
@@ -153,8 +173,10 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
153
173
  else
154
174
  if call? exp and exp.target == HAML_HELPERS and exp.method == :html_escape
155
175
  s = Sexp.new(:escaped_output, exp.first_arg)
176
+ elsif @javascript and call? exp and (exp.method == :j or exp.method == :escape_javascript)
177
+ s = Sexp.new(:escaped_output, exp.first_arg)
156
178
  else
157
- s = Sexp.new(:output, exp)
179
+ s = Sexp.new(default, exp)
158
180
  end
159
181
 
160
182
  s.line(exp.line)
@@ -59,32 +59,4 @@ module Brakeman::ProcessorHelper
59
59
 
60
60
  exp
61
61
  end
62
-
63
- #Returns a class name as a Symbol.
64
- #If class name cannot be determined, returns _exp_.
65
- def class_name exp
66
- case exp
67
- when Sexp
68
- case exp.node_type
69
- when :const
70
- exp.value
71
- when :lvar
72
- exp.value.to_sym
73
- when :colon2
74
- "#{class_name(exp.lhs)}::#{exp.rhs}".to_sym
75
- when :colon3
76
- "::#{exp.value}".to_sym
77
- when :self
78
- @current_class || @current_module || nil
79
- else
80
- exp
81
- end
82
- when Symbol
83
- exp
84
- when nil
85
- nil
86
- else
87
- exp
88
- end
89
- end
90
62
  end
@@ -45,6 +45,33 @@ module Brakeman::Util
45
45
  word + "s"
46
46
  end
47
47
 
48
+ #Returns a class name as a Symbol.
49
+ #If class name cannot be determined, returns _exp_.
50
+ def class_name exp
51
+ case exp
52
+ when Sexp
53
+ case exp.node_type
54
+ when :const
55
+ exp.value
56
+ when :lvar
57
+ exp.value.to_sym
58
+ when :colon2
59
+ "#{class_name(exp.lhs)}::#{exp.rhs}".to_sym
60
+ when :colon3
61
+ "::#{exp.value}".to_sym
62
+ when :self
63
+ @current_class || @current_module || nil
64
+ else
65
+ exp
66
+ end
67
+ when Symbol
68
+ exp
69
+ when nil
70
+ nil
71
+ else
72
+ exp
73
+ end
74
+ end
48
75
 
49
76
  #Takes an Sexp like
50
77
  # (:hash, (:lit, :key), (:str, "value"))
@@ -384,8 +411,9 @@ module Brakeman::Util
384
411
  end
385
412
 
386
413
  def relative_path file
387
- if file and not file.empty? and file.start_with? '/'
388
- Pathname.new(file).relative_path_from(Pathname.new(@tracker.app_path)).to_s
414
+ pname = Pathname.new file
415
+ if file and not file.empty? and pname.absolute?
416
+ pname.relative_path_from(Pathname.new(@tracker.app_path)).to_s
389
417
  else
390
418
  file
391
419
  end
@@ -434,7 +462,12 @@ module Brakeman::Util
434
462
  return "" unless table
435
463
 
436
464
  Brakeman.load_brakeman_dependency 'terminal-table'
437
- output = CSV.generate_line(table.headings.cells.map{|cell| cell.to_s.strip})
465
+ headings = table.headings
466
+ if headings.is_a? Array
467
+ headings = headings.first
468
+ end
469
+
470
+ output = CSV.generate_line(headings.cells.map{|cell| cell.to_s.strip})
438
471
  table.rows.each do |row|
439
472
  output << CSV.generate_line(row.cells.map{|cell| cell.to_s.strip})
440
473
  end
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "3.1.0"
2
+ Version = "3.1.1"
3
3
  end
@@ -90,6 +90,9 @@ module Brakeman::WarningCodes
90
90
  :csrf_not_protected_by_raising_exception => 86,
91
91
  :CVE_2015_3226 => 87,
92
92
  :CVE_2015_3227 => 88,
93
+ :session_key_manipulation => 89,
94
+ :weak_hash_digest => 90,
95
+ :weak_hash_hmac => 91,
93
96
  }
94
97
 
95
98
  def self.code name
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brakeman-min
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Collins
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain:
11
11
  - brakeman-public_cert.pem
12
- date: 2015-08-31 00:00:00.000000000 Z
12
+ date: 2015-09-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-unit
@@ -135,6 +135,7 @@ files:
135
135
  - lib/brakeman/checks/check_select_vulnerability.rb
136
136
  - lib/brakeman/checks/check_send.rb
137
137
  - lib/brakeman/checks/check_send_file.rb
138
+ - lib/brakeman/checks/check_session_manipulation.rb
138
139
  - lib/brakeman/checks/check_session_settings.rb
139
140
  - lib/brakeman/checks/check_simple_format.rb
140
141
  - lib/brakeman/checks/check_single_quotes.rb
@@ -149,6 +150,7 @@ files:
149
150
  - lib/brakeman/checks/check_unsafe_reflection.rb
150
151
  - lib/brakeman/checks/check_unscoped_find.rb
151
152
  - lib/brakeman/checks/check_validation_regex.rb
153
+ - lib/brakeman/checks/check_weak_hash.rb
152
154
  - lib/brakeman/checks/check_without_protection.rb
153
155
  - lib/brakeman/checks/check_xml_dos.rb
154
156
  - lib/brakeman/checks/check_yaml_parsing.rb