sqreen 1.6.5-java → 1.7.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sqreen/callbacks.rb +6 -0
- data/lib/sqreen/events/attack.rb +0 -2
- data/lib/sqreen/frameworks/generic.rb +44 -0
- data/lib/sqreen/instrumentation.rb +11 -5
- data/lib/sqreen/remote_command.rb +9 -2
- data/lib/sqreen/rule_callback.rb +4 -19
- data/lib/sqreen/rules_callbacks.rb +1 -0
- data/lib/sqreen/rules_callbacks/blacklist_ips.rb +44 -0
- data/lib/sqreen/rules_callbacks/count_http_codes.rb +2 -1
- data/lib/sqreen/rules_callbacks/matcher_rule.rb +27 -2
- data/lib/sqreen/rules_callbacks/record_request_context.rb +13 -0
- data/lib/sqreen/rules_callbacks/reflected_xss.rb +2 -7
- data/lib/sqreen/rules_signature.rb +0 -1
- data/lib/sqreen/runner.rb +13 -0
- data/lib/sqreen/safe_json.rb +60 -0
- data/lib/sqreen/session.rb +2 -50
- data/lib/sqreen/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ee9dd561b7874b879607edb6c8f3f51ac3c6b0c
|
4
|
+
data.tar.gz: dea9ef4346206d4b2a5af23dd6e234dd5619abfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72326a2b3cfa4977a12d811ddaeccc35fae049a2163db530e273ea82edcc1fbd4eba4a079950738bb16aaf4d7e592998c8e53a177bb8dc9d2e4d60950af27ef5
|
7
|
+
data.tar.gz: b70f2ef583f7685c0d2a86e9d18b48016ec1a743385de3696f23a3a813c49e58d872a94f4fd5c30b47f9bd7ce90be206e1999d660939b04dbb6d12a25253f2a8
|
data/lib/sqreen/callbacks.rb
CHANGED
@@ -58,6 +58,8 @@ module Sqreen
|
|
58
58
|
# - { :status => :reraise }: reraise
|
59
59
|
# - { :status => :override }: eat exception
|
60
60
|
# - { :retry => :retry }: try the block again
|
61
|
+
#
|
62
|
+
# CB can also declare that they are whitelisted and should not be run at the moment.
|
61
63
|
|
62
64
|
attr_reader :klass, :method
|
63
65
|
|
@@ -72,6 +74,10 @@ module Sqreen
|
|
72
74
|
raise(Sqreen::Exception, 'No callback provided') unless @has_pre || @has_post || @has_failing
|
73
75
|
end
|
74
76
|
|
77
|
+
def whitelisted?
|
78
|
+
false
|
79
|
+
end
|
80
|
+
|
75
81
|
def pre?
|
76
82
|
@has_pre
|
77
83
|
end
|
data/lib/sqreen/events/attack.rb
CHANGED
@@ -45,7 +45,6 @@ module Sqreen
|
|
45
45
|
res = {}
|
46
46
|
rule_p = payload['rule']
|
47
47
|
request_p = payload['request']
|
48
|
-
whitelisted = request_p.delete('whitelisted') if request_p
|
49
48
|
res[:rule_name] = rule_p['name'] if rule_p && rule_p['name']
|
50
49
|
res[:rulespack_id] = rule_p['rulespack_id'] if rule_p && rule_p['rulespack_id']
|
51
50
|
res[:test] = rule_p['test'] if rule_p && rule_p['test']
|
@@ -56,7 +55,6 @@ module Sqreen
|
|
56
55
|
res[:params] = payload['params'] if payload['params']
|
57
56
|
res[:context] = payload['context'] if payload['context']
|
58
57
|
res[:headers] = payload['headers'] if payload['headers']
|
59
|
-
res[:whitelist_match] = whitelisted if whitelisted
|
60
58
|
res
|
61
59
|
end
|
62
60
|
end
|
@@ -291,8 +291,52 @@ module Sqreen
|
|
291
291
|
Dir.getwd
|
292
292
|
end
|
293
293
|
|
294
|
+
WHITELIST_KEY = 'sqreen.whitelisted_request'.freeze
|
295
|
+
|
296
|
+
# Return the current item that whitelist this request
|
297
|
+
# returns nil if request is not whitelisted
|
298
|
+
def whitelisted_match
|
299
|
+
return nil unless request
|
300
|
+
return request.env[WHITELIST_KEY] if request.env.key?(WHITELIST_KEY)
|
301
|
+
request.env[WHITELIST_KEY] = whitelisted_ip || whitelisted_path
|
302
|
+
end
|
303
|
+
|
304
|
+
# Returns the current path that whitelist the request
|
305
|
+
def whitelisted_path
|
306
|
+
path = request_path
|
307
|
+
return nil unless path
|
308
|
+
find_whitelisted_path(path)
|
309
|
+
end
|
310
|
+
|
311
|
+
# Returns the current path that whitelist the request
|
312
|
+
def whitelisted_ip
|
313
|
+
ip = client_ip
|
314
|
+
return nil unless ip
|
315
|
+
find_whitelisted_ip(ip)
|
316
|
+
rescue
|
317
|
+
nil
|
318
|
+
end
|
319
|
+
|
294
320
|
protected
|
295
321
|
|
322
|
+
# Is this a whitelisted path?
|
323
|
+
# return the path witelisted prefix that match path
|
324
|
+
def find_whitelisted_path(rpath)
|
325
|
+
(Sqreen.whitelisted_paths || []).find do |path|
|
326
|
+
rpath.start_with?(path)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
# Is this a whitelisted ip?
|
331
|
+
# return the ip witelisted range that match ip
|
332
|
+
def find_whitelisted_ip(rip)
|
333
|
+
ret = (Sqreen.whitelisted_ips || {}).find do |_, ip|
|
334
|
+
ip.include?(rip)
|
335
|
+
end
|
336
|
+
return nil unless ret
|
337
|
+
ret.first
|
338
|
+
end
|
339
|
+
|
296
340
|
def hook_rack_request(klass)
|
297
341
|
@calling_pid = Process.pid
|
298
342
|
klass.class_eval do
|
@@ -33,6 +33,7 @@ require 'set'
|
|
33
33
|
|
34
34
|
module Sqreen
|
35
35
|
class Instrumentation
|
36
|
+
WHITELISTED_METRIC='whitelisted'.freeze
|
36
37
|
@@override_semaphore = Mutex.new
|
37
38
|
|
38
39
|
## Overriden methods and callbacks globals
|
@@ -54,6 +55,7 @@ module Sqreen
|
|
54
55
|
def self.callback_wrapper_pre(klass, method, instance, *args, &block)
|
55
56
|
Instrumentation.guard_call(method, []) do
|
56
57
|
callbacks = @@registered_callbacks.get(klass, method, :pre)
|
58
|
+
callbacks.reject!(&:whitelisted?)
|
57
59
|
|
58
60
|
returns = []
|
59
61
|
callbacks.each do |cb|
|
@@ -90,6 +92,7 @@ module Sqreen
|
|
90
92
|
def self.callback_wrapper_post(klass, method, return_val, instance, *args, &block)
|
91
93
|
Instrumentation.guard_call(method, []) do
|
92
94
|
callbacks = @@registered_callbacks.get(klass, method, :post)
|
95
|
+
callbacks.reject!(&:whitelisted?)
|
93
96
|
|
94
97
|
returns = []
|
95
98
|
callbacks.reverse_each do |cb|
|
@@ -126,6 +129,7 @@ module Sqreen
|
|
126
129
|
def self.callback_wrapper_failing(exception, klass, method, instance, *args, &block)
|
127
130
|
Instrumentation.guard_call(method, []) do
|
128
131
|
callbacks = @@registered_callbacks.get(klass, method, :failing)
|
132
|
+
callbacks.reject!(&:whitelisted?)
|
129
133
|
|
130
134
|
returns = []
|
131
135
|
callbacks.each do |cb|
|
@@ -506,11 +510,13 @@ module Sqreen
|
|
506
510
|
|
507
511
|
def initialize(metrics_engine = nil)
|
508
512
|
self.metrics_engine = metrics_engine
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
513
|
+
return if metrics_engine.nil?
|
514
|
+
metrics_engine.create_metric('name' => CallCountable::COUNT_CALLS,
|
515
|
+
'period' => 60,
|
516
|
+
'kind' => 'Sum')
|
517
|
+
metrics_engine.create_metric('name' => WHITELISTED_METRIC,
|
518
|
+
'period' => 60,
|
519
|
+
'kind' => 'Sum')
|
514
520
|
end
|
515
521
|
end
|
516
522
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
2
|
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
|
-
require
|
3
|
+
require 'sqreen/log'
|
4
|
+
require 'sqreen/events/remote_exception'
|
4
5
|
|
5
6
|
module Sqreen
|
6
7
|
# Execute and sanitize remote commands
|
@@ -13,6 +14,7 @@ module Sqreen
|
|
13
14
|
:features_change => :change_features,
|
14
15
|
:force_logout => :shutdown,
|
15
16
|
:paths_whitelist => :change_whitelisted_paths,
|
17
|
+
:ips_whitelist => :change_whitelisted_ips,
|
16
18
|
}.freeze
|
17
19
|
|
18
20
|
attr_reader :uuid
|
@@ -27,7 +29,12 @@ module Sqreen
|
|
27
29
|
failing = validate_command(runner)
|
28
30
|
return failing if failing
|
29
31
|
Sqreen.log.debug format('processing command %s', @name)
|
30
|
-
|
32
|
+
begin
|
33
|
+
output = runner.send(KNOWN_COMMANDS[@name], *@params, context_infos)
|
34
|
+
rescue => e
|
35
|
+
Sqreen::RemoteException.record(e)
|
36
|
+
return { :status => false, :reason => "error: #{e.inspect}" }
|
37
|
+
end
|
31
38
|
format_output(output)
|
32
39
|
end
|
33
40
|
|
data/lib/sqreen/rule_callback.rb
CHANGED
@@ -46,39 +46,24 @@ module Sqreen
|
|
46
46
|
@rule[Attrs::RULESPACK_ID]
|
47
47
|
end
|
48
48
|
|
49
|
+
def whitelisted?
|
50
|
+
framework && !framework.whitelisted_match.nil?
|
51
|
+
end
|
52
|
+
|
49
53
|
# Recommend taking an action (optionnally adding more data/context)
|
50
54
|
#
|
51
55
|
# This will format the requested action and optionnally
|
52
56
|
# override it if it should not be taken (should not block for example)
|
53
57
|
def advise_action(action, additional_data = {})
|
54
58
|
return if action.nil? && additional_data.empty?
|
55
|
-
if %w(override raise).include?(action.to_s) && framework
|
56
|
-
prefix = find_whitelisted_path(framework.request_path.to_s)
|
57
|
-
if prefix
|
58
|
-
Sqreen.log.debug { "Trying to block on whitelisted path #{prefix}" }
|
59
|
-
action = nil
|
60
|
-
end
|
61
|
-
end
|
62
59
|
additional_data.merge(:status => action)
|
63
60
|
end
|
64
61
|
|
65
|
-
# Is this a whitelisted path?
|
66
|
-
# return the path witelisted prefix that match path
|
67
|
-
def find_whitelisted_path(rpath)
|
68
|
-
(Sqreen.whitelisted_paths || []).find do |path|
|
69
|
-
rpath.start_with?(path)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
62
|
# Record an attack event into Sqreen system
|
74
63
|
# @param infos [Hash] Additional information about request
|
75
64
|
def record_event(infos)
|
76
65
|
payload = @payload_generator.payload(framework, @rule)
|
77
66
|
payload['infos'] = infos
|
78
|
-
if framework && payload['request']
|
79
|
-
prefix = find_whitelisted_path(framework.request_path.to_s)
|
80
|
-
payload['request']['whitelisted'] = prefix
|
81
|
-
end
|
82
67
|
Attack.record(payload)
|
83
68
|
end
|
84
69
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
|
+
|
4
|
+
require 'ipaddr'
|
5
|
+
|
6
|
+
require 'sqreen/rule_callback'
|
7
|
+
|
8
|
+
module Sqreen
|
9
|
+
module Rules
|
10
|
+
# Looks for a blacklisted ip and block
|
11
|
+
class BlacklistIPsCB < RuleCB
|
12
|
+
def initialize(klass, method, rule_hash)
|
13
|
+
super(klass, method, rule_hash)
|
14
|
+
@ips = Hash[@data['values'].map { |v| [v, IPAddr.new(v)] }]
|
15
|
+
raise ArgumentError.new("no ips given") if @ips.empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
def pre(_inst, *_args, &_block)
|
19
|
+
return unless framework
|
20
|
+
ip = framework.client_ip
|
21
|
+
return unless ip
|
22
|
+
found = find_blacklisted_ip(ip)
|
23
|
+
return unless found
|
24
|
+
Sqreen.log.debug { "Found blacklisted IP #{ip} - found: #{found}" }
|
25
|
+
record_observation('blacklisted', found, 1)
|
26
|
+
advise_action(:raise)
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
# Is this a blacklisted ip?
|
32
|
+
# return the ip blacklisted range that match ip
|
33
|
+
def find_blacklisted_ip(rip)
|
34
|
+
ret = (@ips || {}).find do |_, ip|
|
35
|
+
ip.include?(rip)
|
36
|
+
end
|
37
|
+
return nil unless ret
|
38
|
+
ret.first
|
39
|
+
rescue
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'sqreen/rule_attributes'
|
5
5
|
require 'sqreen/rule_callback'
|
6
|
+
require 'sqreen/safe_json'
|
6
7
|
|
7
8
|
module Sqreen
|
8
9
|
module Rules
|
@@ -31,7 +32,7 @@ module Sqreen
|
|
31
32
|
key = @accessors.map do |accessor|
|
32
33
|
accessor.resolve(binding, framework, inst, args, @data, rv)
|
33
34
|
end
|
34
|
-
record_observation(@metric_category,
|
35
|
+
record_observation(@metric_category, SafeJSON.dump(key), 1)
|
35
36
|
advise_action(nil)
|
36
37
|
end
|
37
38
|
end
|
@@ -73,6 +73,7 @@ module Sqreen
|
|
73
73
|
|
74
74
|
def match(str)
|
75
75
|
return if str.nil? || str.empty?
|
76
|
+
str = enforce_encoding(str)
|
76
77
|
istr = str.downcase
|
77
78
|
|
78
79
|
@string.each do |type, cases|
|
@@ -92,11 +93,35 @@ module Sqreen
|
|
92
93
|
end
|
93
94
|
end
|
94
95
|
|
95
|
-
|
96
|
-
|
96
|
+
if defined?(Encoding)
|
97
|
+
@regexp_patterns.each do |p|
|
98
|
+
next unless Encoding.compatible?(p, str)
|
99
|
+
return p if p.match(str)
|
100
|
+
end
|
101
|
+
else
|
102
|
+
@regexp_patterns.each do |p|
|
103
|
+
warn(Encoding.compatible?(p, str).inspect)
|
104
|
+
return p if p.match(str)
|
105
|
+
end
|
97
106
|
end
|
98
107
|
nil
|
99
108
|
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def enforce_encoding(str)
|
113
|
+
return str unless str.is_a?(String)
|
114
|
+
return str if str.ascii_only?
|
115
|
+
encoded8bit = str.encoding.name == 'ASCII-8BIT'
|
116
|
+
return str if !encoded8bit && str.valid_encoding?
|
117
|
+
str.chars.map do |v|
|
118
|
+
if !v.valid_encoding? || (encoded8bit && !v.ascii_only?)
|
119
|
+
''
|
120
|
+
else
|
121
|
+
v
|
122
|
+
end
|
123
|
+
end.join
|
124
|
+
end
|
100
125
|
end
|
101
126
|
|
102
127
|
# A configurable matcher rule
|
@@ -2,13 +2,26 @@
|
|
2
2
|
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
3
|
|
4
4
|
require 'sqreen/rule_callback'
|
5
|
+
require 'sqreen/instrumentation'
|
5
6
|
|
6
7
|
module Sqreen
|
7
8
|
module Rules
|
8
9
|
# Save request context for handling further down
|
9
10
|
class RecordRequestContext < RuleCB
|
11
|
+
def whitelisted?
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
10
15
|
def pre(_inst, *args, &_block)
|
11
16
|
framework.store_request(args[0])
|
17
|
+
wh = framework.whitelisted_match
|
18
|
+
if wh
|
19
|
+
unless Sqreen.features.key?('whitelisted_metric') &&
|
20
|
+
!Sqreen.features['whitelisted_metric']
|
21
|
+
record_observation(Instrumentation::WHITELISTED_METRIC, wh, 1)
|
22
|
+
end
|
23
|
+
Sqreen.log.debug { "Request was whitelisted because of #{wh}" }
|
24
|
+
end
|
12
25
|
advise_action(nil)
|
13
26
|
end
|
14
27
|
|
@@ -47,8 +47,7 @@ module Sqreen
|
|
47
47
|
return unless report_dangerous_xss?(saved_value)
|
48
48
|
|
49
49
|
# potential XSS! let's escape
|
50
|
-
if block
|
51
|
-
(!framework || !find_whitelisted_path(framework.request_path.to_s))
|
50
|
+
if block
|
52
51
|
args[0].replace(CGI.escape_html(value))
|
53
52
|
end
|
54
53
|
|
@@ -150,9 +149,6 @@ module Sqreen
|
|
150
149
|
|
151
150
|
return if !found_xss || !block
|
152
151
|
# potential XSS! let's escape
|
153
|
-
if framework && find_whitelisted_path(framework.request_path.to_s)
|
154
|
-
return nil
|
155
|
-
end
|
156
152
|
args[-1] = new_attrs
|
157
153
|
r = inst.send(method, *args)
|
158
154
|
{ :status => :skip, :new_return_value => r }
|
@@ -213,8 +209,7 @@ module Sqreen
|
|
213
209
|
|
214
210
|
return unless block
|
215
211
|
# potential XSS! let's escape
|
216
|
-
if block
|
217
|
-
(!framework || !find_whitelisted_path(framework.request_path.to_s))
|
212
|
+
if block
|
218
213
|
args[0] = CGI.escape_html(value)
|
219
214
|
r = inst.send(method, *args)
|
220
215
|
return { :status => :skip, :new_return_value => r }
|
data/lib/sqreen/runner.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
2
|
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
3
|
|
4
|
+
require 'ipaddr'
|
4
5
|
require 'timeout'
|
5
6
|
require 'json'
|
6
7
|
|
@@ -53,6 +54,11 @@ module Sqreen
|
|
53
54
|
def update_whitelisted_paths(paths)
|
54
55
|
@whitelisted_paths = paths.freeze
|
55
56
|
end
|
57
|
+
|
58
|
+
attr_reader :whitelisted_ips
|
59
|
+
def update_whitelisted_ips(paths)
|
60
|
+
@whitelisted_ips = Hash[paths.map { |v| [v, IPAddr.new(v)] }].freeze
|
61
|
+
end
|
56
62
|
end
|
57
63
|
|
58
64
|
# Main running job class for the agent
|
@@ -87,6 +93,7 @@ module Sqreen
|
|
87
93
|
@token = @configuration.get(:token)
|
88
94
|
@url = @configuration.get(:url)
|
89
95
|
Sqreen.update_whitelisted_paths([])
|
96
|
+
Sqreen.update_whitelisted_ips({})
|
90
97
|
raise(Sqreen::Exception, 'no url found') unless @url
|
91
98
|
raise(Sqreen::TokenNotFoundException, 'no token found') unless @token
|
92
99
|
|
@@ -244,6 +251,12 @@ module Sqreen
|
|
244
251
|
true
|
245
252
|
end
|
246
253
|
|
254
|
+
def change_whitelisted_ips(ips, _context_infos = {})
|
255
|
+
return false unless ips.respond_to?(:each)
|
256
|
+
Sqreen.update_whitelisted_ips(ips)
|
257
|
+
true
|
258
|
+
end
|
259
|
+
|
247
260
|
def change_features(new_features, _context_infos = {})
|
248
261
|
old = features
|
249
262
|
self.features = new_features
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require 'sqreen/log'
|
7
|
+
|
8
|
+
module Sqreen
|
9
|
+
# Safely dump datastructure in json (more resilient to encoding errors)
|
10
|
+
class SafeJSON
|
11
|
+
def self.dump(data)
|
12
|
+
JSON.generate(data)
|
13
|
+
rescue JSON::GeneratorError, Encoding::UndefinedConversionError
|
14
|
+
Sqreen.log.debug('Payload could not be encoded enforcing recode')
|
15
|
+
JSON.generate(rencode_payload(data))
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.rencode_payload(obj, max_depth = 20)
|
19
|
+
max_depth -= 1
|
20
|
+
return obj if max_depth < 0
|
21
|
+
return rencode_array(obj, max_depth) if obj.is_a?(Array)
|
22
|
+
return enforce_encoding(obj) unless obj.is_a?(Hash)
|
23
|
+
nobj = {}
|
24
|
+
obj.each do |k, v|
|
25
|
+
safe_k = rencode_payload(k, max_depth)
|
26
|
+
nobj[safe_k] = case v
|
27
|
+
when Array
|
28
|
+
rencode_array(v, max_depth)
|
29
|
+
when Hash
|
30
|
+
rencode_payload(v, max_depth)
|
31
|
+
when String
|
32
|
+
enforce_encoding(v)
|
33
|
+
else # for example integers
|
34
|
+
v
|
35
|
+
end
|
36
|
+
end
|
37
|
+
nobj
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.rencode_array(array, max_depth)
|
41
|
+
array.map! { |e| rencode_payload(e, max_depth - 1) }
|
42
|
+
array
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.enforce_encoding(str)
|
46
|
+
return str unless str.is_a?(String)
|
47
|
+
return str if str.ascii_only?
|
48
|
+
encoded8bit = str.encoding.name == 'ASCII-8BIT'
|
49
|
+
return str if !encoded8bit && str.valid_encoding?
|
50
|
+
r = str.chars.map do |v|
|
51
|
+
if !v.valid_encoding? || (encoded8bit && !v.ascii_only?)
|
52
|
+
v.bytes.map { |c| "\\x#{c.to_s(16).upcase}" }.join
|
53
|
+
else
|
54
|
+
v
|
55
|
+
end
|
56
|
+
end.join
|
57
|
+
"SqBytes[#{r}]"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/sqreen/session.rb
CHANGED
@@ -6,9 +6,9 @@ require 'sqreen/serializer'
|
|
6
6
|
require 'sqreen/runtime_infos'
|
7
7
|
require 'sqreen/events/remote_exception'
|
8
8
|
require 'sqreen/exception'
|
9
|
+
require 'sqreen/safe_json'
|
9
10
|
|
10
11
|
require 'net/https'
|
11
|
-
require 'json'
|
12
12
|
require 'uri'
|
13
13
|
require 'openssl'
|
14
14
|
require 'zlib'
|
@@ -187,7 +187,7 @@ module Sqreen
|
|
187
187
|
json_data = nil
|
188
188
|
unless data.nil?
|
189
189
|
serialized = Serializer.serialize(data)
|
190
|
-
json_data = compress(
|
190
|
+
json_data = compress(SafeJSON.dump(serialized))
|
191
191
|
end
|
192
192
|
@con.post(path, json_data, headers)
|
193
193
|
else
|
@@ -209,13 +209,6 @@ module Sqreen
|
|
209
209
|
res
|
210
210
|
end
|
211
211
|
|
212
|
-
def self.encode_payload(data)
|
213
|
-
JSON.generate(data)
|
214
|
-
rescue JSON::GeneratorError, Encoding::UndefinedConversionError
|
215
|
-
Sqreen.log.debug('Payload could not be encoded enforcing recode')
|
216
|
-
JSON.generate(rencode_payload(data))
|
217
|
-
end
|
218
|
-
|
219
212
|
def compress(data)
|
220
213
|
return data unless request_compression
|
221
214
|
out = StringIO.new
|
@@ -225,47 +218,6 @@ module Sqreen
|
|
225
218
|
out.string
|
226
219
|
end
|
227
220
|
|
228
|
-
def self.rencode_payload(obj, max_depth = 20)
|
229
|
-
max_depth -= 1
|
230
|
-
return obj if max_depth < 0
|
231
|
-
return rencode_array(obj, max_depth) if obj.is_a?(Array)
|
232
|
-
return enforce_encoding(obj) unless obj.is_a?(Hash)
|
233
|
-
nobj = {}
|
234
|
-
obj.each do |k, v|
|
235
|
-
safe_k = rencode_payload(k, max_depth)
|
236
|
-
nobj[safe_k] = case v
|
237
|
-
when Array
|
238
|
-
rencode_array(v, max_depth)
|
239
|
-
when Hash
|
240
|
-
rencode_payload(v, max_depth)
|
241
|
-
when String
|
242
|
-
enforce_encoding(v)
|
243
|
-
else # for example integers
|
244
|
-
v
|
245
|
-
end
|
246
|
-
end
|
247
|
-
nobj
|
248
|
-
end
|
249
|
-
|
250
|
-
def self.rencode_array(array, max_depth)
|
251
|
-
array.map! { |e| rencode_payload(e, max_depth - 1) }
|
252
|
-
array
|
253
|
-
end
|
254
|
-
|
255
|
-
def self.enforce_encoding(str)
|
256
|
-
return str unless str.is_a?(String)
|
257
|
-
return str if str.ascii_only?
|
258
|
-
encoded8bit = str.encoding.name == 'ASCII-8BIT'
|
259
|
-
return str if !encoded8bit && str.valid_encoding?
|
260
|
-
str.chars.map do |v|
|
261
|
-
if !v.valid_encoding? || (encoded8bit && !v.ascii_only?)
|
262
|
-
v.bytes.map { |c| "\\x#{c.to_s(16).upcase}" }.join
|
263
|
-
else
|
264
|
-
v
|
265
|
-
end
|
266
|
-
end.join
|
267
|
-
end
|
268
|
-
|
269
221
|
def login(framework)
|
270
222
|
headers = { 'x-api-key' => @token }
|
271
223
|
|
data/lib/sqreen/version.rb
CHANGED
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.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Sqreen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: execjs
|
@@ -92,6 +92,7 @@ files:
|
|
92
92
|
- lib/sqreen/rules_callbacks.rb
|
93
93
|
- lib/sqreen/rules_callbacks/binding_accessor_matcher.rb
|
94
94
|
- lib/sqreen/rules_callbacks/binding_accessor_metrics.rb
|
95
|
+
- lib/sqreen/rules_callbacks/blacklist_ips.rb
|
95
96
|
- lib/sqreen/rules_callbacks/count_http_codes.rb
|
96
97
|
- lib/sqreen/rules_callbacks/crawler_user_agent_matches.rb
|
97
98
|
- lib/sqreen/rules_callbacks/crawler_user_agent_matches_metrics.rb
|
@@ -110,6 +111,7 @@ files:
|
|
110
111
|
- lib/sqreen/rules_signature.rb
|
111
112
|
- lib/sqreen/runner.rb
|
112
113
|
- lib/sqreen/runtime_infos.rb
|
114
|
+
- lib/sqreen/safe_json.rb
|
113
115
|
- lib/sqreen/sdk.rb
|
114
116
|
- lib/sqreen/serializer.rb
|
115
117
|
- lib/sqreen/session.rb
|
@@ -134,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
136
|
version: '0'
|
135
137
|
requirements: []
|
136
138
|
rubyforge_project:
|
137
|
-
rubygems_version: 2.6.
|
139
|
+
rubygems_version: 2.6.12
|
138
140
|
signing_key:
|
139
141
|
specification_version: 4
|
140
142
|
summary: Sqreen Ruby agent
|