sqreen 1.20.4.beta1 → 1.20.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18fc090589982cc7e09d74263a3bbb17ae9180f00afd8425c47498a0f8b75e36
4
- data.tar.gz: 074c3c9cad84ef1a52e6fd7ce1a4db5431920f59298e5b930206ca9a996141e9
3
+ metadata.gz: d7324df5cecbb626299a4e048550c6f7c5a3e15bef2eecc8d89011d0342914aa
4
+ data.tar.gz: eabb5203769dcf898d8a4e373c6cfee7e5b0eac8bbfc3977fb8924a54504b126
5
5
  SHA512:
6
- metadata.gz: afd27c8a52c0c5e21685b9bf6b346a28ca43ff297c529c1976d7197bc132d51a92f2ac52dcb4de150cd8c752c4875b4fdd3baf8e59560a0c1952c4df12585572
7
- data.tar.gz: 2e6d09aceaf1dcc351537b0a34e4459e7f1d4659a231cd515e6f01ec42f0515dc40ff89f14adb7094a6971f86fe3983e984bf35f8242b8f047405c164ef0874c
6
+ metadata.gz: 5e7f4bb53e01c0f5328a5190b189c82b596bcf28eada2104b1491c5601b1275866ef8950ae9ad92c91303011636a3c11ebcb3c3dbccd75280d6b89c1c69d301a
7
+ data.tar.gz: 77770ff7b00b9d07ea7f4137eadce1e840bc1ad94e885b42623354707306ebd42425187833e0403e33d02bea7471010bf934bda9010c5fe1d604715c5daf88c1
@@ -1,3 +1,12 @@
1
+ ## 1.20.4
2
+
3
+ * Fix missing budget check
4
+ * Improve performance
5
+ * Align internal setting name for WAF
6
+ * Include response information in all payloads
7
+ * Improve robustness against invalid Unicode
8
+ * Prevent rule execution to pursue in early block cases
9
+
1
10
  ## 1.20.4.beta1
2
11
 
3
12
  * Add optional dynamic time budget
@@ -67,7 +67,7 @@ module Sqreen
67
67
  return true if rem <= 0
68
68
  if hash.is_a?(Array)
69
69
  return hash.any? do |v|
70
- ConditionEvaluator.hash_key_include?(values, v, min_value_size, rem - 1)
70
+ hash_key_include?(values, v, min_value_size, rem - 1)
71
71
  end
72
72
  end
73
73
 
@@ -81,7 +81,13 @@ module Sqreen
81
81
  if hkey.respond_to?(:empty?) && hkey.empty?
82
82
  false
83
83
  else
84
- values.include?(hkey.to_s) || ConditionEvaluator.hash_key_include?(values, hval, min_value_size, rem - 1)
84
+ key_incl = if values.is_a?(String)
85
+ str_include?(values, hkey.to_s)
86
+ else
87
+ values.include?(hkey.to_s)
88
+ end
89
+
90
+ key_incl || hash_key_include?(values, hval, min_value_size, rem - 1)
85
91
  end
86
92
  end
87
93
  end
@@ -8,7 +8,6 @@
8
8
  require 'json'
9
9
  require 'sqreen/log'
10
10
  require 'sqreen/event'
11
- require 'sqreen/encoding_sanitizer'
12
11
  require 'sqreen/sensitive_data_redactor'
13
12
 
14
13
  module Sqreen
@@ -69,6 +69,8 @@ module Sqreen
69
69
 
70
70
  # signals require request section to be present
71
71
  payload_requests << 'request'
72
+ # for signals, response is optional, but the backend team wants them
73
+ payload_requests << 'response'
72
74
  payload = payload_creator.payload(payload_requests)
73
75
  payload[:observed] = observed_items
74
76
 
@@ -6,6 +6,7 @@
6
6
  require 'sqreen/aggregated_metric'
7
7
  require 'sqreen/log/loggable'
8
8
  require 'sqreen/legacy/waf_redactions'
9
+ require 'sqreen/kit/string_sanitizer'
9
10
 
10
11
  module Sqreen
11
12
  module Legacy
@@ -166,7 +167,7 @@ module Sqreen
166
167
  res[:request][:parameters] = payload['params'] if payload['params']
167
168
  res[:request][:headers] = payload['headers'] if payload['headers']
168
169
 
169
- res = Sqreen::EncodingSanitizer.sanitize(res)
170
+ res = Sqreen::Kit::StringSanitizer.sanitize(res)
170
171
 
171
172
  if rr.redactor
172
173
  res[:request], redacted = rr.redactor.redact(res[:request])
@@ -120,9 +120,13 @@ module Sqreen
120
120
 
121
121
  cb_class = ExecJSCB if js
122
122
 
123
- if cbname && Rules.const_defined?(cbname)
124
- # Only load callbacks from sqreen
125
- cb_class = Rules.const_get(cbname)
123
+ if cbname
124
+ cb_class = if cbname.include?('::')
125
+ # Only load callbacks from sqreen
126
+ Rules.walk_const_get(cbname) if cbname.start_with?('::Sqreen::', 'Sqreen::')
127
+ else
128
+ Rules.const_get(cbname) if Rules.const_defined?(cbname) # rubocop:disable Style/IfInsideElse
129
+ end
126
130
  end
127
131
 
128
132
  if cb_class.nil?
@@ -55,12 +55,12 @@ module Sqreen
55
55
  end
56
56
 
57
57
  def respond_page
58
- page = open(File.join(File.dirname(__FILE__), '../attack_detected.html'))
58
+ @page ||= File.read(File.join(File.dirname(__FILE__), '../attack_detected.html'))
59
59
  headers = {
60
60
  'Content-Type' => 'text/html',
61
- 'Content-Length' => page.size.to_s,
61
+ 'Content-Length' => @page.size.to_s,
62
62
  }
63
- [@status_code, headers, page]
63
+ [@status_code, headers, [@page]]
64
64
  end
65
65
  end
66
66
  end
@@ -11,7 +11,7 @@ require 'sqreen/safe_json'
11
11
  require 'sqreen/exception'
12
12
  require 'sqreen/util/capper'
13
13
  require 'sqreen/dependency/libsqreen'
14
- require 'sqreen/encoding_sanitizer'
14
+ require 'sqreen/kit/string_sanitizer'
15
15
 
16
16
  module Sqreen
17
17
  module Rules
@@ -60,7 +60,7 @@ module Sqreen
60
60
  end
61
61
 
62
62
  # 0 for using defaults (PW_RUN_TIMEOUT)
63
- @max_run_budget_us = (@data['values'].fetch('budget_in_ms', 0) * 1000).to_i
63
+ @max_run_budget_us = (@data['values'].fetch('max_budget_ms', 0) * 1000).to_i
64
64
  @max_run_budget_us = INFINITE_BUDGET_US if @max_run_budget_us >= INFINITE_BUDGET_US
65
65
 
66
66
  Sqreen.log.debug { "Max WAF run budget for #{@waf_rule_name} set to #{@max_run_budget_us} us" }
@@ -82,7 +82,7 @@ module Sqreen
82
82
  waf_args = binding_accessors.each_with_object({}) do |(e, b), h|
83
83
  h[e] = capper.call(b.resolve(*env))
84
84
  end
85
- waf_args = Sqreen::EncodingSanitizer.sanitize(waf_args)
85
+ waf_args = Sqreen::Kit::StringSanitizer.sanitize(waf_args)
86
86
 
87
87
  if budget
88
88
  rem_budget_s = budget - (Sqreen.time - start)
@@ -4,5 +4,5 @@
4
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
5
 
6
6
  module Sqreen
7
- VERSION = '1.20.4.beta1'.freeze
7
+ VERSION = '1.20.4'.freeze
8
8
  end
@@ -5,6 +5,7 @@
5
5
 
6
6
  require 'sqreen/weave/legacy'
7
7
  require 'sqreen/weave/budget'
8
+ require 'sqreen/graft/hook'
8
9
  require 'sqreen/graft/hook_point'
9
10
  require 'sqreen/call_countable'
10
11
  require 'sqreen/rules'
@@ -172,8 +173,8 @@ class Sqreen::Weave::Legacy::Instrumentation
172
173
  request_timer.start
173
174
  sqreen_timer = Sqreen::Graft::Timer.new("sqreen")
174
175
  budget = Sqreen::Weave::Budget.current
175
- request_budget_threshold = budget.threshold
176
- request_budget_ratio = budget.ratio
176
+ request_budget_threshold = budget.threshold if budget
177
+ request_budget_ratio = budget.ratio if budget
177
178
  request_budget_is_dynamic = !request_budget_ratio.nil?
178
179
  request_budget = !request_budget_threshold.nil?
179
180
  timed_level = (Sqreen.features['perf_level'] || 1).to_i
@@ -212,12 +213,16 @@ class Sqreen::Weave::Legacy::Instrumentation
212
213
  if request[:timed_level] >= 1
213
214
  request[:timed_callbacks].each do |timer|
214
215
  duration = timer.duration
216
+
215
217
  timer.tag =~ /weave,rule=(.*)$/ && rule = $1
216
- timer.tag =~ /@before/ && whence = 'pre'
217
- timer.tag =~ /@after/ && whence = 'post'
218
- timer.tag =~ /@raised/ && whence = 'failing'
218
+ next unless rule
219
219
 
220
- next unless rule && whence
220
+ whence = case timer.tag
221
+ when /@before/ then 'pre'
222
+ when /@after/ then 'post'
223
+ when /@raised/ then 'failing'
224
+ end
225
+ next unless whence
221
226
 
222
227
  metric_name = "sq.#{rule}.#{whence}"
223
228
  metrics_engine.update(metric_name, now, nil, duration * 1000)
@@ -270,12 +275,16 @@ class Sqreen::Weave::Legacy::Instrumentation
270
275
  tallies = Hash.new(0.0)
271
276
  request[:timed_callbacks].each do |timer|
272
277
  duration = timer.duration
278
+
273
279
  timer.tag =~ /weave,rule=(.*)$/ && rule = $1
274
- timer.tag =~ /@before/ && whence = 'pre'
275
- timer.tag =~ /@after/ && whence = 'post'
276
- timer.tag =~ /@raised/ && whence = 'failing'
280
+ next unless rule
277
281
 
278
- next unless rule && whence
282
+ whence = case timer.tag
283
+ when /@before/ then 'pre'
284
+ when /@after/ then 'post'
285
+ when /@raised/ then 'failing'
286
+ end
287
+ next unless whence
279
288
 
280
289
  metric_name = "req.sq.#{rule}.#{whence}"
281
290
  tallies[metric_name] += duration
@@ -364,15 +373,25 @@ class Sqreen::Weave::Legacy::Instrumentation
364
373
  end
365
374
  end
366
375
 
367
- case ret[:status]
368
- when :skip, 'skip'
369
- throw(b, b.return(ret[:new_return_value]).break!) if ret.key?(:new_return_value)
370
- when :modify_args, 'modify_args'
371
- throw(b, b.args(ret[:args]))
372
- when :raise, 'raise'
373
- throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
374
- throw(b, b.raise(Sqreen::AttackBlocked.new("Sqreen blocked a security threat (type: #{callback.rule_name}). No action is required.")))
375
- end unless ret.nil? || !ret.is_a?(Hash)
376
+ next if ret.nil? || !ret.is_a?(Hash)
377
+
378
+ throw_val =
379
+ case ret[:status]
380
+ when :skip, 'skip'
381
+ b.return(ret[:new_return_value]).break! if ret.key?(:new_return_value)
382
+ when :modify_args, 'modify_args'
383
+ b.args(ret[:args])
384
+ when :raise, 'raise'
385
+ if ret.key?(:exception)
386
+ b.raise(ret[:exception])
387
+ else
388
+ b.raise(Sqreen::AttackBlocked.new("Sqreen blocked a security threat (type: #{callback.rule_name}). No action is required."))
389
+ end
390
+ end
391
+
392
+ next unless throw_val
393
+ throw_val.break! if ret[:skip_rem_cbs]
394
+ throw(b, throw_val)
376
395
  end
377
396
  end
378
397
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqreen
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.20.4.beta1
4
+ version: 1.20.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sqreen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-14 00:00:00.000000000 Z
11
+ date: 2020-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sqreen-backport
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.2.1
33
+ version: 0.2.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.2.1
40
+ version: 0.2.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: sq_mini_racer
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -123,7 +123,6 @@ files:
123
123
  - lib/sqreen/dependency/sentry.rb
124
124
  - lib/sqreen/dependency/sinatra.rb
125
125
  - lib/sqreen/deprecation.rb
126
- - lib/sqreen/encoding_sanitizer.rb
127
126
  - lib/sqreen/endpoint_testing.rb
128
127
  - lib/sqreen/error_handling_middleware.rb
129
128
  - lib/sqreen/event.rb
@@ -279,9 +278,7 @@ metadata:
279
278
  changelog_uri: https://docs.sqreen.com/ruby/release-notes/
280
279
  source_code_uri: https://github.com/sqreen/ruby-agent
281
280
  bug_tracker_uri: https://github.com/sqreen/ruby-agent/issues
282
- post_install_message: |2
283
- This is a Sqreen beta release and may not work in all situations.
284
- Make sure to review CHANGELOG.md for important details.
281
+ post_install_message:
285
282
  rdoc_options: []
286
283
  require_paths:
287
284
  - lib
@@ -292,11 +289,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
292
289
  version: 1.9.3
293
290
  required_rubygems_version: !ruby/object:Gem::Requirement
294
291
  requirements:
295
- - - ">"
292
+ - - ">="
296
293
  - !ruby/object:Gem::Version
297
- version: 1.3.1
294
+ version: '0'
298
295
  requirements: []
299
- rubygems_version: 3.1.2
296
+ rubygems_version: 3.1.4
300
297
  signing_key:
301
298
  specification_version: 4
302
299
  summary: Sqreen Ruby agent
@@ -1,27 +0,0 @@
1
- # typed: true
2
-
3
- # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
- # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
-
6
- module Sqreen
7
- class EncodingSanitizer
8
- def self.sanitize(obj)
9
- case obj
10
- when String
11
- sanitize_string(obj)
12
- when Array
13
- obj.map { |e| sanitize(e) }
14
- when Hash
15
- obj.each_with_object({}) { |(k, v), h| h[k] = sanitize(v) }
16
- else
17
- obj
18
- end
19
- end
20
-
21
- def self.sanitize_string(s)
22
- return s if s.encoding.name == 'UTF-8' && s.valid_encoding?
23
-
24
- s.encode('UTF-16', :invalid => :replace, :undef => :replace).encode('UTF-8')
25
- end
26
- end
27
- end