sqreen 1.19.0.beta1 → 1.19.4

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