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 +4 -4
- data/CHANGELOG.md +21 -2
- data/lib/sqreen/rules/not_found_cb.rb +2 -0
- data/lib/sqreen/rules/waf_cb.rb +28 -8
- data/lib/sqreen/runner.rb +5 -1
- data/lib/sqreen/version.rb +1 -1
- data/lib/sqreen/weave/legacy/instrumentation.rb +25 -7
- metadata +14 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1a0d2f8489dac7835a9d2135b0e35c15848a4fa094f7912f9979a83a9d2670e
|
4
|
+
data.tar.gz: 9bfc5db45531824d4f968f45fe495c9fad5da7c258c368fec5821aba8f66b124
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2c2e5a91c6e415c6003dae1c3ca775b9d40eaacb34e4d28d07c991e46941bcb0bb0f1e9d01bdb1644562fb35852c9fb222bd8f1b83a008be3871ee6a5880cb9
|
7
|
+
data.tar.gz: 9164671762553af1f0cd658e3d654432a3eebfe81050f32d9cf8fc7c36fedb8c40a530629e57a16bec62536a080a931a2f2b34ba1fcb33521ab2964db38bc224
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,25 @@
|
|
1
|
-
## 1.19.
|
1
|
+
## 1.19.4
|
2
2
|
|
3
|
-
*
|
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
|
data/lib/sqreen/rules/waf_cb.rb
CHANGED
@@ -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
|
-
|
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, :
|
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
|
-
|
58
|
-
|
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
|
-
|
77
|
-
|
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({
|
101
|
+
record_event({ waf_data: data })
|
82
102
|
advise_action(nil)
|
83
103
|
when :block
|
84
|
-
record_event({
|
104
|
+
record_event({ waf_data: data })
|
85
105
|
advise_action(:raise)
|
86
106
|
when :good
|
87
107
|
advise_action(nil)
|
data/lib/sqreen/runner.rb
CHANGED
@@ -121,7 +121,11 @@ module Sqreen
|
|
121
121
|
|
122
122
|
self.metrics_engine = MetricsStore.new
|
123
123
|
|
124
|
-
|
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)
|
data/lib/sqreen/version.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
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.
|
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-
|
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.
|
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.
|
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
|
-
|
237
|
-
|
238
|
-
|
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:
|
254
|
+
version: '0'
|
252
255
|
requirements: []
|
253
|
-
rubygems_version: 3.
|
256
|
+
rubygems_version: 3.1.2
|
254
257
|
signing_key:
|
255
258
|
specification_version: 4
|
256
259
|
summary: Sqreen Ruby agent
|