sqreen 1.19.0.beta1 → 1.19.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: 0ffc604ca6c427fc4f689c67c3973a00bf83d6f0207f394c4df333bea1690799
4
- data.tar.gz: 3b36a33e74f0dabb4ab75449807d2c2d2459f3edebe5e324ae593f12487815db
3
+ metadata.gz: a1a0d2f8489dac7835a9d2135b0e35c15848a4fa094f7912f9979a83a9d2670e
4
+ data.tar.gz: 9bfc5db45531824d4f968f45fe495c9fad5da7c258c368fec5821aba8f66b124
5
5
  SHA512:
6
- metadata.gz: 622abad5c40c24d5740dde29bd53da136ccbe40f357b541f0e9d9fec5131e61aa71f391d525eaf4819dbffb22901d7ca9a186c2b615f9b5f0e617254bce40bdc
7
- data.tar.gz: d4072082a4aaf7a22e6d7ccaa0699f19b029c0236c6a5be12125e2c8ee5de3cbd99afa4a7560a772f2d1ac6224511f3ef600daa9b13fbae4cf7d85b65147bdd4
6
+ metadata.gz: f2c2e5a91c6e415c6003dae1c3ca775b9d40eaacb34e4d28d07c991e46941bcb0bb0f1e9d01bdb1644562fb35852c9fb222bd8f1b83a008be3871ee6a5880cb9
7
+ data.tar.gz: 9164671762553af1f0cd658e3d654432a3eebfe81050f32d9cf8fc7c36fedb8c40a530629e57a16bec62536a080a931a2f2b34ba1fcb33521ab2964db38bc224
@@ -1,6 +1,25 @@
1
- ## 1.19.0.beta1
1
+ ## 1.19.4
2
2
 
3
- * Improve compatibility with a new optional instrumentation engine
3
+ * Fix signature check
4
+
5
+ ## 1.19.3
6
+
7
+ * Improve WAF PII protection
8
+
9
+ ## 1.19.2
10
+
11
+ * Handle unexpected rule callback return values more gracefully
12
+ * Fix incorrect return value for 404 native callback
13
+
14
+ ## 1.19.1
15
+
16
+ * Fix LocalJumpError when reaching a Rack app nested in a Rails app
17
+
18
+ ## 1.19.0
19
+
20
+ * Upgrade WAF features via libsqreen 0.6.1
21
+ * Improve time defensiveness in WAF
22
+ * Improve compatibility with APM agents via a new optional instrumentation engine
4
23
  * Fix action reloading not being entirely cleared on reload
5
24
  * Improve handling of hash symbol keys in some security rules
6
25
  * Fix constant resolution scope on agent boot
@@ -24,6 +24,8 @@ module Sqreen
24
24
  exception = env['action_dispatch.exception']
25
25
 
26
26
  record_from_env(ua, script_name, path_info, verb, override, host, exception)
27
+
28
+ nil
27
29
  end
28
30
 
29
31
  def record_from_env(ua, script_name, path_info, verb, override, host, exception)
@@ -11,11 +11,15 @@ 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
15
 
15
16
  module Sqreen
16
17
  module Rules
17
18
  class WAFCB < RuleCB
18
- BUDGET_MAX = 5
19
+ # 2^30 -1 or 2^62 -1
20
+ MAX_FIXNUM = 1.size == 4 ? 1_073_741_823 : 4_611_686_018_427_387_903
21
+ # will be converted to a long, so better not to overflow
22
+ INFINITE_BUDGET_US = MAX_FIXNUM
19
23
 
20
24
  def self.libsqreen?
21
25
  Sqreen::Dependency::LibSqreen.required?
@@ -25,7 +29,7 @@ module Sqreen
25
29
  Sqreen::Dependency.const_exist?('LibSqreen::WAF')
26
30
  end
27
31
 
28
- attr_reader :binding_accessors, :budget, :waf_rule_name
32
+ attr_reader :binding_accessors, :max_run_budget_us, :waf_rule_name
29
33
 
30
34
  def initialize(*args)
31
35
  super(*args)
@@ -54,8 +58,12 @@ module Sqreen
54
58
  @binding_accessors = @data['values'].fetch('binding_accessors', []).each_with_object({}) do |e, h|
55
59
  h[e] = BindingAccessor.new(e)
56
60
  end
57
- @budget = (@data['values'].fetch('budget_in_ms', nil) || BUDGET_MAX) * 1000
58
- Sqreen.log.debug("WAF budget for #{@waf_rule_name} set to #{@budget}us")
61
+
62
+ # 0 for using defaults (PW_RUN_TIMEOUT)
63
+ @max_run_budget_us = (@data['values'].fetch('budget_in_ms', 0) * 1000).to_i
64
+ @max_run_budget_us = INFINITE_BUDGET_US if @max_run_budget_us >= INFINITE_BUDGET_US
65
+
66
+ Sqreen.log.debug { "Max WAF run budget for #{@waf_rule_name} set to #{@max_run_budget_us} us" }
59
67
 
60
68
  ObjectSpace.define_finalizer(self, WAFCB.finalizer(@waf_rule_name.dup))
61
69
  end
@@ -68,20 +76,32 @@ module Sqreen
68
76
 
69
77
  env = [binding, framework, instance, args]
70
78
 
79
+ start = Sqreen.time if budget
80
+
71
81
  capper = Sqreen::Util::Capper.new(string_size_cap: 4096, size_cap: 150, depth_cap: 10)
72
82
  waf_args = binding_accessors.each_with_object({}) do |(e, b), h|
73
83
  h[e] = capper.call(b.resolve(*env))
74
84
  end
75
85
  waf_args = Sqreen::EncodingSanitizer.sanitize(waf_args)
76
- waf_budget = [self.budget, budget && budget * 1_000_000].compact.min.to_i
77
- action, data = ::LibSqreen::WAF.run(waf_rule_name, waf_args, waf_budget)
86
+
87
+ if budget
88
+ rem_budget_s = budget - (Sqreen.time - start)
89
+ return advise_action(nil) if rem_budget_s <= 0.0
90
+
91
+ waf_gen_budget_us = [(rem_budget_s * 1_000_000).to_i, MAX_FIXNUM].min
92
+ else # no budget
93
+ waf_gen_budget_us = INFINITE_BUDGET_US
94
+ end
95
+
96
+ action, data = ::LibSqreen::WAF.run(waf_rule_name, waf_args,
97
+ waf_gen_budget_us, @max_run_budget_us)
78
98
 
79
99
  case action
80
100
  when :monitor
81
- record_event({ 'waf_data' => data })
101
+ record_event({ waf_data: data })
82
102
  advise_action(nil)
83
103
  when :block
84
- record_event({ 'waf_data' => data })
104
+ record_event({ waf_data: data })
85
105
  advise_action(:raise)
86
106
  when :good
87
107
  advise_action(nil)
@@ -121,7 +121,11 @@ module Sqreen
121
121
 
122
122
  self.metrics_engine = MetricsStore.new
123
123
 
124
- if @configuration.get(:weave)
124
+ needs_weave = proc do
125
+ Gem::Specification.select { |s| s.name == 'scout_apm' && Gem::Requirement.new('>= 2.5.2').satisfied_by?(Gem::Version.new(s.version)) }.any?
126
+ end
127
+
128
+ if @configuration.get(:weave) || needs_weave.call
125
129
  @instrumenter = Sqreen::Weave::Legacy::Instrumentation.new(metrics_engine)
126
130
  else
127
131
  @instrumenter = Sqreen::Legacy::Instrumentation.new(metrics_engine)
@@ -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.19.0.beta1'.freeze
7
+ VERSION = '1.19.4'.freeze
8
8
  end
@@ -8,6 +8,7 @@ require 'sqreen/graft/hook_point'
8
8
  require 'sqreen/call_countable'
9
9
  require 'sqreen/rules'
10
10
  require 'sqreen/rules/record_request_context'
11
+ require 'sqreen/sqreen_signed_verifier'
11
12
 
12
13
  class Sqreen::Weave::Legacy::Instrumentation
13
14
  attr_accessor :metrics_engine
@@ -76,11 +77,23 @@ class Sqreen::Weave::Legacy::Instrumentation
76
77
  if strategy == :prepend && !Module.respond_to?(:prepend)
77
78
  Sqreen::Weave.logger.warn { "strategy: #{strategy.inspect} unavailable, falling back to :chain" }
78
79
  strategy = :chain
80
+ elsif strategy == :chain && Gem::Specification.select { |s| s.name == 'scout_apm' && Gem::Requirement.new('>= 2.5.2').satisfied_by?(Gem::Version.new(s.version)) }.any?
81
+ Sqreen::Weave.logger.warn { "strategy: #{strategy.inspect} unavailable with scout_apm >= 2.5.2, switching to :prepend" }
82
+ strategy = :prepend
79
83
  end
80
84
  Sqreen::Weave.logger.debug { "strategy: #{strategy.inspect}" }
81
85
 
82
86
  ### set up rule signature verifier
83
87
  verifier = nil
88
+ if Sqreen.features['rules_signature'] &&
89
+ Sqreen.config_get(:rules_verify_signature) == true &&
90
+ !defined?(::JRUBY_VERSION)
91
+ verifier = Sqreen::SqreenSignedVerifier.new
92
+ Sqreen::Weave.logger.debug('Rules signature enabled')
93
+ else
94
+ Sqreen::Weave.logger.debug('Rules signature disabled')
95
+ end
96
+
84
97
  ### force clean instrumentation callback list
85
98
  @hooks = []
86
99
  ### for each rule description
@@ -108,6 +121,8 @@ class Sqreen::Weave::Legacy::Instrumentation
108
121
  @hooks << request_hook
109
122
  request_hook.add do
110
123
  before('wave,meta,request', rank: -100000, mandatory: true) do |_call|
124
+ next unless Sqreen.instrumentation_ready
125
+
111
126
  uuid = SecureRandom.uuid
112
127
  now = Sqreen::Graft::Timer.read
113
128
  Thread.current[:sqreen_http_request] = {
@@ -130,6 +145,9 @@ class Sqreen::Weave::Legacy::Instrumentation
130
145
 
131
146
  ensured('weave,meta,request', rank: 100000, mandatory: true) do |_call|
132
147
  request = Thread.current[:sqreen_http_request]
148
+
149
+ next if request.nil?
150
+
133
151
  Thread.current[:sqreen_http_request] = nil
134
152
  now = Sqreen::Graft::Timer.read
135
153
  utc_now = Time.now.utc
@@ -261,7 +279,7 @@ class Sqreen::Weave::Legacy::Instrumentation
261
279
  hook.add do
262
280
  if callback.pre?
263
281
  before(rule, rank: priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
264
- return unless Sqreen.instrumentation_ready
282
+ next unless Thread.current[:sqreen_http_request]
265
283
 
266
284
  i = call.instance
267
285
  a = call.args
@@ -288,13 +306,13 @@ class Sqreen::Weave::Legacy::Instrumentation
288
306
  when :raise, 'raise'
289
307
  throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
290
308
  throw(b, b.raise(Sqreen::AttackBlocked.new("Sqreen blocked a security threat (type: #{callback.rule_name}). No action is required.")))
291
- end unless ret.nil?
309
+ end unless ret.nil? || !ret.is_a?(Hash)
292
310
  end
293
311
  end
294
312
 
295
313
  if callback.post?
296
314
  after(rule, rank: -priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
297
- return unless Sqreen.instrumentation_ready
315
+ next unless Thread.current[:sqreen_http_request]
298
316
 
299
317
  i = call.instance
300
318
  v = call.returned
@@ -320,13 +338,13 @@ class Sqreen::Weave::Legacy::Instrumentation
320
338
  when :raise, 'raise'
321
339
  throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
322
340
  throw(b, b.raise(Sqreen::AttackBlocked.new("Sqreen blocked a security threat (type: #{callback.rule_name}). No action is required.")))
323
- end unless ret.nil?
341
+ end unless ret.nil? || !ret.is_a?(Hash)
324
342
  end
325
343
  end
326
344
 
327
345
  if callback.failing?
328
346
  raised(rule, rank: priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
329
- return unless Sqreen.instrumentation_ready
347
+ next unless Thread.current[:sqreen_http_request]
330
348
 
331
349
  i = call.instance
332
350
  e = call.raised
@@ -346,7 +364,7 @@ class Sqreen::Weave::Legacy::Instrumentation
346
364
  end
347
365
  Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#failing instance=#{i} => return=#{ret.inspect}" }
348
366
 
349
- raise e if ret.nil?
367
+ throw(b, b.raise(e)) if ret.nil? || !ret.is_a?(Hash)
350
368
 
351
369
  case ret[:status]
352
370
  when :override, 'override'
@@ -360,7 +378,7 @@ class Sqreen::Weave::Legacy::Instrumentation
360
378
  throw(b, b.raise(e))
361
379
  else
362
380
  throw(b, b.raise(e))
363
- end unless ret.nil?
381
+ end unless ret.nil? || !ret.is_a?(Hash)
364
382
  end
365
383
  end
366
384
  end.install
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.19.0.beta1
4
+ version: 1.19.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-05-11 00:00:00.000000000 Z
11
+ date: 2020-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sq_mini_racer
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.3.0.0
33
+ version: 0.6.1.0.0
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.3.0.0
40
+ version: 0.6.1.0.0
41
41
  description: Sqreen is a SaaS based Application protection and monitoring platform
42
42
  that integrates directly into your Ruby applications. Learn more at https://sqreen.com.
43
43
  email: contact@sqreen.com
@@ -232,10 +232,13 @@ files:
232
232
  homepage: https://www.sqreen.com/
233
233
  licenses:
234
234
  - Sqreen
235
- metadata: {}
236
- post_install_message: |2
237
- This is a Sqreen beta release and may not work in all situations.
238
- Make sure to review CHANGELOG.md for important details.
235
+ metadata:
236
+ homepage_uri: https://sqreen.com
237
+ documentation_uri: https://docs.sqreen.com/
238
+ changelog_uri: https://docs.sqreen.com/ruby/release-notes/
239
+ source_code_uri: https://github.com/sqreen/ruby-agent
240
+ bug_tracker_uri: https://github.com/sqreen/ruby-agent/issues
241
+ post_install_message:
239
242
  rdoc_options: []
240
243
  require_paths:
241
244
  - lib
@@ -246,11 +249,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
246
249
  version: 1.9.3
247
250
  required_rubygems_version: !ruby/object:Gem::Requirement
248
251
  requirements:
249
- - - ">"
252
+ - - ">="
250
253
  - !ruby/object:Gem::Version
251
- version: 1.3.1
254
+ version: '0'
252
255
  requirements: []
253
- rubygems_version: 3.0.3
256
+ rubygems_version: 3.1.2
254
257
  signing_key:
255
258
  specification_version: 4
256
259
  summary: Sqreen Ruby agent