sqreen 1.18.3.beta1 → 1.18.3.beta2
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 +4 -4
- data/CHANGELOG.md +0 -5
- data/lib/sqreen/actions.rb +11 -337
- data/lib/sqreen/actions/base.rb +110 -0
- data/lib/sqreen/actions/block_ip.rb +32 -0
- data/lib/sqreen/actions/block_user.rb +44 -0
- data/lib/sqreen/actions/ip_range_indexed_action_class.rb +36 -0
- data/lib/sqreen/actions/ip_ranges_index.rb +36 -0
- data/lib/sqreen/actions/redirect_ip.rb +40 -0
- data/lib/sqreen/actions/redirect_user.rb +45 -0
- data/lib/sqreen/actions/repository.rb +24 -0
- data/lib/sqreen/actions/unknown_action_type.rb +16 -0
- data/lib/sqreen/actions/user_action_class.rb +41 -0
- data/lib/sqreen/agent.rb +4 -1
- data/lib/sqreen/attack_blocked.rb +17 -0
- data/lib/sqreen/binding_accessor.rb +9 -102
- data/lib/sqreen/binding_accessor/path_elem.rb +8 -0
- data/lib/sqreen/binding_accessor/transforms.rb +107 -0
- data/lib/sqreen/capped_queue.rb +2 -0
- data/lib/sqreen/{callbacks.rb → cb.rb} +1 -53
- data/lib/sqreen/{callback_tree.rb → cb_tree.rb} +2 -2
- data/lib/sqreen/condition_evaluator.rb +22 -5
- data/lib/sqreen/configuration.rb +3 -0
- data/lib/sqreen/default_cb.rb +20 -0
- data/lib/sqreen/deferred_logger.rb +63 -0
- data/lib/sqreen/deliveries.rb +10 -0
- data/lib/sqreen/deliveries/batch.rb +7 -1
- data/lib/sqreen/deliveries/simple.rb +5 -0
- data/lib/sqreen/dependency/rails.rb +4 -0
- data/lib/sqreen/dependency/sinatra.rb +4 -0
- data/lib/sqreen/error_handling_middleware.rb +30 -0
- data/lib/sqreen/event.rb +2 -0
- data/lib/sqreen/events/attack.rb +2 -0
- data/lib/sqreen/events/request_record.rb +11 -56
- data/lib/sqreen/exception.rb +9 -40
- data/lib/sqreen/formatter_with_tid.rb +45 -0
- data/lib/sqreen/framework_cb.rb +28 -0
- data/lib/sqreen/frameworks.rb +7 -0
- data/lib/sqreen/frameworks/generic.rb +5 -1
- data/lib/sqreen/frameworks/rails.rb +2 -0
- data/lib/sqreen/frameworks/request_recorder.rb +3 -0
- data/lib/sqreen/frameworks/sinatra.rb +2 -0
- data/lib/sqreen/frameworks/sqreen_test.rb +2 -0
- data/lib/sqreen/instrumentation.rb +5 -5
- data/lib/sqreen/invalid_signature_exception.rb +8 -0
- data/lib/{sqreen-alt.rb → sqreen/js.rb} +6 -1
- data/lib/sqreen/js/call_context.rb +10 -0
- data/lib/sqreen/js/context_pool.rb +60 -0
- data/lib/sqreen/js/exec_js_runnable.rb +20 -0
- data/lib/sqreen/js/execjs_adapter.rb +6 -47
- data/lib/sqreen/js/executable_js.rb +12 -0
- data/lib/sqreen/js/js_service.rb +2 -22
- data/lib/sqreen/js/js_service_adapter.rb +18 -0
- data/lib/sqreen/js/mini_racer_adapter.rb +6 -180
- data/lib/sqreen/js/mini_racer_executable_js.rb +142 -0
- data/lib/sqreen/js/thread_local_exec_js_runnable.rb +47 -0
- data/lib/sqreen/log.rb +8 -188
- data/lib/sqreen/logger.rb +83 -0
- data/lib/sqreen/metrics_store.rb +3 -11
- data/lib/sqreen/metrics_store/already_registered_metric.rb +11 -0
- data/lib/sqreen/metrics_store/unknown_metric.rb +11 -0
- data/lib/sqreen/metrics_store/unregistered_metric.rb +11 -0
- data/lib/sqreen/middleware.rb +0 -44
- data/lib/sqreen/mono_time.rb +2 -0
- data/lib/sqreen/node.rb +44 -0
- data/lib/sqreen/not_implemented_yet.rb +8 -0
- data/lib/sqreen/null_logger.rb +24 -0
- data/lib/sqreen/payload_creator.rb +2 -19
- data/lib/sqreen/payload_creator/header_section.rb +28 -0
- data/lib/sqreen/prefix.rb +33 -0
- data/lib/sqreen/rails_middleware.rb +14 -0
- data/lib/sqreen/remote_command.rb +1 -8
- data/lib/sqreen/remote_command/failure_output.rb +11 -0
- data/lib/sqreen/rules.rb +32 -2
- data/lib/sqreen/{rule_attributes.rb → rules/attrs.rb} +0 -0
- data/lib/sqreen/{rules_callbacks/sdk_auth_track.rb → rules/auth_track_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/binding_accessor_matcher.rb → rules/binding_accessor_matcher_cb.rb} +4 -8
- data/lib/sqreen/{rules_callbacks → rules}/binding_accessor_metrics.rb +1 -1
- data/lib/sqreen/{rules_callbacks/blacklist_ips.rb → rules/blacklist_ips_cb.rb} +3 -2
- data/lib/sqreen/{rules_callbacks → rules}/count_http_codes.rb +2 -2
- data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches.rb → rules/crawler_user_agent_matches_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches_metrics.rb → rules/crawler_user_agent_matches_metrics_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/custom_error.rb → rules/custom_error_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/devise_auth_track.rb → rules/devise_auth_track_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/devise_signup_track.rb → rules/devise_signup_track_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/execjs.rb → rules/execjs_cb.rb} +49 -50
- data/lib/sqreen/{rules_callbacks/headers_insert.rb → rules/headers_insert_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks → rules}/matcher_rule.rb +2 -2
- data/lib/sqreen/{rules_callbacks/not_found.rb → rules/not_found_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/rails_parameters.rb → rules/rails_parameters_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks → rules}/record_request_context.rb +1 -1
- data/lib/sqreen/{rules_callbacks/regexp_rule.rb → rules/regexp_rule_cb.rb} +1 -1
- data/lib/sqreen/{rule_callback.rb → rules/rule_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks → rules}/run_req_start_actions.rb +4 -2
- data/lib/sqreen/{rules_callbacks → rules}/run_user_actions.rb +1 -1
- data/lib/sqreen/{rules_callbacks/shell_env.rb → rules/shell_env_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/sdk_signup_track.rb → rules/signup_track_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks → rules}/update_request_context.rb +1 -1
- data/lib/sqreen/{rules_callbacks/url_matches.rb → rules/url_matches_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/user_agent_matches.rb → rules/user_agent_matches_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/waf.rb → rules/waf_cb.rb} +7 -3
- data/lib/sqreen/{rules_callbacks/reflected_xss.rb → rules/xss_cb.rb} +10 -7
- data/lib/sqreen/run_when_called_cb.rb +21 -0
- data/lib/sqreen/sensitive_data_redactor.rb +111 -0
- data/lib/sqreen/signature_verifier.rb +20 -0
- data/lib/sqreen/sinatra_middleware.rb +14 -0
- data/lib/sqreen/{rules_signature.rb → sqreen_signed_verifier.rb} +5 -17
- data/lib/sqreen/token_invalid_exception.rb +8 -0
- data/lib/sqreen/token_not_found_exception.rb +9 -0
- data/lib/sqreen/trie.rb +3 -64
- data/lib/sqreen/unauthorized.rb +8 -0
- data/lib/sqreen/util.rb +2 -0
- data/lib/sqreen/util/capped_array.rb +30 -0
- data/lib/sqreen/util/capped_hash.rb +36 -0
- data/lib/sqreen/util/capped_string.rb +22 -0
- data/lib/sqreen/util/capper.rb +57 -0
- data/lib/sqreen/version.rb +1 -1
- data/lib/sqreen/waf_error.rb +18 -0
- metadata +85 -36
- data/lib/sqreen/rules_callbacks.rb +0 -36
- data/lib/sqreen/rules_callbacks/inspect_rule.rb +0 -25
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
3
|
+
|
4
|
+
require 'sqreen/exception'
|
5
|
+
require 'sqreen/actions/base'
|
6
|
+
require 'sqreen/actions/ip_range_indexed_action_class'
|
7
|
+
|
8
|
+
module Sqreen
|
9
|
+
module Actions
|
10
|
+
# Block a list of IP address ranges. Standard "raise" behavior.
|
11
|
+
class BlockIp < Base
|
12
|
+
extend IpRangeIndexedActionClass
|
13
|
+
|
14
|
+
self.type_name = 'block_ip'
|
15
|
+
|
16
|
+
def initialize(id, opts, _params = {})
|
17
|
+
# no need to store the ranges for this action, the index filter the class
|
18
|
+
super(id, opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
def do_run(client_ip)
|
22
|
+
e = Sqreen::AttackBlocked.new("Blocked client's IP #{client_ip} " \
|
23
|
+
"(action: #{id}). No action is required")
|
24
|
+
{ :status => :raise, :exception => e, :skip_rem_cbs => true }
|
25
|
+
end
|
26
|
+
|
27
|
+
def event_properties(client_ip)
|
28
|
+
{ 'ip_address' => client_ip }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
3
|
+
|
4
|
+
require 'sqreen/log'
|
5
|
+
require 'sqreen/exception'
|
6
|
+
require 'sqreen/actions/base'
|
7
|
+
require 'sqreen/actions/user_action_class'
|
8
|
+
|
9
|
+
module Sqreen
|
10
|
+
module Actions
|
11
|
+
# Blocks a user at the point Sqreen::identify()
|
12
|
+
# or Sqreen::auth_track() are called
|
13
|
+
class BlockUser < Base
|
14
|
+
extend UserActionClass
|
15
|
+
|
16
|
+
self.type_name = 'block_user'
|
17
|
+
|
18
|
+
def initialize(id, opts, _params = {})
|
19
|
+
super(id, opts)
|
20
|
+
end
|
21
|
+
|
22
|
+
def do_run(identity_params)
|
23
|
+
Sqreen.log.info(
|
24
|
+
"Will raise due to user being blocked by action #{id}. " \
|
25
|
+
"Blocked user identity: #{identity_params}"
|
26
|
+
)
|
27
|
+
|
28
|
+
e = Sqreen::AttackBlocked.new(
|
29
|
+
"Blocked user with identity #{identity_params} " \
|
30
|
+
'due to automatic security response. No action is required'
|
31
|
+
)
|
32
|
+
|
33
|
+
{
|
34
|
+
:status => :raise,
|
35
|
+
:exception => e,
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def event_properties(identity_params)
|
40
|
+
{ 'user' => identity_params }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
3
|
+
|
4
|
+
require 'sqreen/actions/ip_ranges_index'
|
5
|
+
|
6
|
+
module Sqreen
|
7
|
+
module Actions
|
8
|
+
module IpRangeIndexedActionClass
|
9
|
+
include IpRangesIndex
|
10
|
+
|
11
|
+
def actions_matching(client_ip)
|
12
|
+
matching_actions client_ip
|
13
|
+
end
|
14
|
+
|
15
|
+
def index(params, action)
|
16
|
+
ranges = parse_ip_ranges params
|
17
|
+
|
18
|
+
ranges.each do |r|
|
19
|
+
add_prefix r, action
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# returns array of prefixes in string form
|
26
|
+
def parse_ip_ranges(params)
|
27
|
+
ranges = params['ip_cidr']
|
28
|
+
unless ranges && ranges.is_a?(Array) && !ranges.empty?
|
29
|
+
raise 'no non-empty ip_cidr array present'
|
30
|
+
end
|
31
|
+
|
32
|
+
ranges
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
3
|
+
|
4
|
+
require 'ipaddr'
|
5
|
+
require 'sqreen/trie'
|
6
|
+
require 'sqreen/prefix'
|
7
|
+
|
8
|
+
module Sqreen
|
9
|
+
module Actions
|
10
|
+
module IpRangesIndex
|
11
|
+
def add_prefix(prefix_str, data)
|
12
|
+
@trie_v4 ||= Sqreen::Trie.new
|
13
|
+
@trie_v6 ||= Sqreen::Trie.new(nil, nil, Socket::AF_INET6)
|
14
|
+
prefix = Sqreen::Prefix.from_str(prefix_str, data)
|
15
|
+
trie = prefix.family == Socket::AF_INET6 ? @trie_v6 : @trie_v4
|
16
|
+
trie.insert prefix
|
17
|
+
end
|
18
|
+
|
19
|
+
def matching_actions(client_ip)
|
20
|
+
parsed_ip = IPAddr.new(client_ip.gsub(/%[^%\/]+/, ''))
|
21
|
+
trie = parsed_ip.family == Socket::AF_INET6 ? @trie_v6 : @trie_v4
|
22
|
+
return [] unless trie
|
23
|
+
found = trie.search_matching(parsed_ip.to_i, parsed_ip.family)
|
24
|
+
return [] unless found.size > 0
|
25
|
+
|
26
|
+
Sqreen.log.debug("Client ip #{client_ip} matches #{found.inspect}")
|
27
|
+
found.map(&:data)
|
28
|
+
end
|
29
|
+
|
30
|
+
def clear
|
31
|
+
@trie_v4 = Sqreen::Trie.new
|
32
|
+
@trie_v6 = Sqreen::Trie.new(nil, nil, Socket::AF_INET6)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
3
|
+
|
4
|
+
require 'sqreen/log'
|
5
|
+
require 'sqreen/exception'
|
6
|
+
require 'sqreen/actions/base'
|
7
|
+
|
8
|
+
module Sqreen
|
9
|
+
module Actions
|
10
|
+
# Block a list of IP address ranges by forcefully redirecting the user
|
11
|
+
# to a specific URL.
|
12
|
+
class RedirectIp < Base
|
13
|
+
extend IpRangeIndexedActionClass
|
14
|
+
|
15
|
+
self.type_name = 'redirect_ip'
|
16
|
+
|
17
|
+
attr_reader :redirect_url
|
18
|
+
|
19
|
+
def initialize(id, opts, params = {})
|
20
|
+
super(id, opts)
|
21
|
+
@redirect_url = params['url']
|
22
|
+
raise "no url provided for action #{id}" unless @redirect_url
|
23
|
+
end
|
24
|
+
|
25
|
+
def do_run(client_ip)
|
26
|
+
Sqreen.log.info "Will request redirect for client with IP #{client_ip} " \
|
27
|
+
"(action: #{id})."
|
28
|
+
{
|
29
|
+
:status => :skip,
|
30
|
+
:new_return_value => [303, { 'Location' => @redirect_url }, ['']],
|
31
|
+
:skip_rem_cbs => true,
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def event_properties(client_ip)
|
36
|
+
{ 'ip_address' => client_ip, 'url' => @redirect_url }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
3
|
+
|
4
|
+
require 'sqreen/log'
|
5
|
+
require 'sqreen/exception'
|
6
|
+
require 'sqreen/actions/base'
|
7
|
+
require 'sqreen/actions/user_action_class'
|
8
|
+
|
9
|
+
module Sqreen
|
10
|
+
module Actions
|
11
|
+
# Redirects a user at the point Sqreen::identify()
|
12
|
+
# or Sqreen::auth_track() are called
|
13
|
+
class RedirectUser < Base
|
14
|
+
extend UserActionClass
|
15
|
+
|
16
|
+
self.type_name = 'redirect_user'
|
17
|
+
|
18
|
+
def initialize(id, opts, params = {})
|
19
|
+
super(id, opts)
|
20
|
+
@redirect_url = params['url']
|
21
|
+
raise "no url provided for action #{id}" unless @redirect_url
|
22
|
+
end
|
23
|
+
|
24
|
+
def do_run(identity_params)
|
25
|
+
Sqreen.log.info 'Will request redirect for user with identity ' \
|
26
|
+
"#{identity_params} (action: #{id})."
|
27
|
+
|
28
|
+
e = Sqreen::AttackBlocked.new(
|
29
|
+
"Redirected user with identity #{identity_params} " \
|
30
|
+
'due to automatic security response. No action is required'
|
31
|
+
)
|
32
|
+
e.redirect_url = @redirect_url
|
33
|
+
|
34
|
+
{
|
35
|
+
:status => :raise,
|
36
|
+
:exception => e,
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def event_properties(identity_params)
|
41
|
+
{ 'user' => identity_params }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
3
|
+
|
4
|
+
module Sqreen
|
5
|
+
module Actions
|
6
|
+
# Where the currently loaded actions are stored. Singleton
|
7
|
+
class Repository
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
def add(params, action)
|
11
|
+
action.class.index(params || {}, action)
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(action_class, key)
|
15
|
+
action_class = Base.get_type_class(action_class) unless action_class.class == Class
|
16
|
+
action_class.actions_matching key
|
17
|
+
end
|
18
|
+
|
19
|
+
def clear
|
20
|
+
Base.known_subclasses.each(&:clear)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
3
|
+
|
4
|
+
module Sqreen
|
5
|
+
# Implements actions (behavior taken in response to agent signals)
|
6
|
+
module Actions
|
7
|
+
# Exception for when an unknown action type is gotten from the server
|
8
|
+
class UnknownActionType < ::Sqreen::Exception
|
9
|
+
attr_reader :action_type
|
10
|
+
def initialize(action_type)
|
11
|
+
super("no such action type: #{action_type}. Must be one of #{Base.known_types}")
|
12
|
+
@action_type = action_type
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
3
|
+
|
4
|
+
require 'sqreen/exception'
|
5
|
+
|
6
|
+
module Sqreen
|
7
|
+
module Actions
|
8
|
+
module UserActionClass
|
9
|
+
def actions_matching(identity_params)
|
10
|
+
return [] unless @idx
|
11
|
+
key = stringify_keys(identity_params)
|
12
|
+
actions = @idx[key]
|
13
|
+
actions || []
|
14
|
+
end
|
15
|
+
|
16
|
+
def index(params, action)
|
17
|
+
@idx ||= {}
|
18
|
+
users = params['users']
|
19
|
+
raise ::Sqreen::Exception, 'nil "users" param for block_user action' if users.nil?
|
20
|
+
raise ::Sqreen::Exception, '"users" param must be an array' unless users.is_a? Array
|
21
|
+
|
22
|
+
users.each do |u|
|
23
|
+
@idx[u] ||= []
|
24
|
+
@idx[u] << action
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def clear
|
29
|
+
@idx = {}
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def stringify_keys(hash)
|
35
|
+
Hash[
|
36
|
+
hash.map { |k, v| [k.to_s, v] }
|
37
|
+
]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/sqreen/agent.rb
CHANGED
@@ -5,10 +5,13 @@ require 'sqreen/version'
|
|
5
5
|
require 'sqreen/instrumentation'
|
6
6
|
require 'sqreen/session'
|
7
7
|
require 'sqreen/runner'
|
8
|
-
require 'sqreen/callbacks'
|
9
8
|
require 'sqreen/log'
|
10
9
|
require 'sqreen/exception'
|
11
10
|
require 'sqreen/configuration'
|
11
|
+
require 'sqreen/cb'
|
12
|
+
require 'sqreen/default_cb'
|
13
|
+
require 'sqreen/run_when_called_cb'
|
14
|
+
require 'sqreen/framework_cb'
|
12
15
|
require 'sqreen/events/attack'
|
13
16
|
require 'sqreen/sdk'
|
14
17
|
require 'sqreen/dependency/detector'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
3
|
+
|
4
|
+
require 'sqreen/exception'
|
5
|
+
|
6
|
+
module Sqreen
|
7
|
+
# This exception name is particularly important since it is often seen by
|
8
|
+
# Sqreen users when watching their logs. It should not raise any concern to
|
9
|
+
# them.
|
10
|
+
class AttackBlocked < Sqreen::Exception
|
11
|
+
attr_accessor :redirect_url
|
12
|
+
|
13
|
+
def log_message(msg)
|
14
|
+
Sqreen.log.warn(msg)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -3,12 +3,13 @@
|
|
3
3
|
|
4
4
|
require 'strscan'
|
5
5
|
require 'sqreen/exception'
|
6
|
-
|
6
|
+
|
7
|
+
require 'sqreen/binding_accessor/path_elem'
|
8
|
+
require 'sqreen/binding_accessor/transforms'
|
7
9
|
|
8
10
|
module Sqreen
|
9
11
|
# the value located at the given binding
|
10
12
|
class BindingAccessor
|
11
|
-
PathElem = Struct.new(:kind, :value)
|
12
13
|
attr_reader :path, :expression, :final_transform, :transform_args
|
13
14
|
|
14
15
|
# Expression to be accessed
|
@@ -67,6 +68,7 @@ module Sqreen
|
|
67
68
|
CONSTANT_KIND = 'constant'.freeze
|
68
69
|
METHOD_KIND = 'method'.freeze
|
69
70
|
INDEX_KIND = 'index'.freeze
|
71
|
+
NIL_KIND = 'nil'.freeze
|
70
72
|
SQREEN_VAR_KIND = 'sqreen-variable'.freeze
|
71
73
|
|
72
74
|
if binding.respond_to?(:local_variable_get)
|
@@ -101,6 +103,8 @@ module Sqreen
|
|
101
103
|
current_value.send(component[:value])
|
102
104
|
when INDEX_KIND
|
103
105
|
current_value[component[:value]]
|
106
|
+
when NIL_KIND
|
107
|
+
current_value
|
104
108
|
when SQREEN_VAR_KIND
|
105
109
|
resolve_sqreen_variable(component[:value], *env)
|
106
110
|
else
|
@@ -176,6 +180,8 @@ module Sqreen
|
|
176
180
|
PathElem.new(SYMBOL_KIND, @scan[1].to_sym)
|
177
181
|
elsif @scan.scan(/'((?:\\.|[^\\'])*)'/)
|
178
182
|
PathElem.new(STRING_KIND, @scan[1])
|
183
|
+
elsif @scan.scan(/nil/)
|
184
|
+
PathElem.new(NIL_KIND, nil)
|
179
185
|
end
|
180
186
|
end
|
181
187
|
|
@@ -248,110 +254,11 @@ module Sqreen
|
|
248
254
|
end
|
249
255
|
end
|
250
256
|
|
251
|
-
# Available final transformations
|
252
|
-
module Transforms
|
253
|
-
def flat_keys(value, max_iter = 1000)
|
254
|
-
return nil if value.nil?
|
255
|
-
seen = Set.new
|
256
|
-
look_into = [value]
|
257
|
-
keys = []
|
258
|
-
idx = 0
|
259
|
-
until look_into.empty? || max_iter <= idx
|
260
|
-
idx += 1
|
261
|
-
val = look_into.pop
|
262
|
-
next unless seen.add?(val.object_id)
|
263
|
-
case val
|
264
|
-
when Hash
|
265
|
-
keys.concat(val.keys)
|
266
|
-
look_into.concat(val.values)
|
267
|
-
when Array
|
268
|
-
look_into.concat(val)
|
269
|
-
else
|
270
|
-
next if val.respond_to?(:seek)
|
271
|
-
val.each { |v| look_into << v } if val.respond_to?(:each)
|
272
|
-
end
|
273
|
-
end
|
274
|
-
keys
|
275
|
-
end
|
276
|
-
|
277
|
-
def flat_values(value, max_iter = 1000)
|
278
|
-
return nil if value.nil?
|
279
|
-
seen = Set.new
|
280
|
-
look_into = [value]
|
281
|
-
values = []
|
282
|
-
idx = 0
|
283
|
-
until look_into.empty? || max_iter <= idx
|
284
|
-
idx += 1
|
285
|
-
val = look_into.shift
|
286
|
-
next unless seen.add?(val.object_id)
|
287
|
-
case val
|
288
|
-
when Hash
|
289
|
-
look_into.concat(val.values)
|
290
|
-
when Array
|
291
|
-
look_into.concat(val)
|
292
|
-
else
|
293
|
-
next if val.respond_to?(:seek)
|
294
|
-
if val.respond_to?(:each)
|
295
|
-
val.each { |v| look_into << v }
|
296
|
-
else
|
297
|
-
values << val
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
301
|
-
values
|
302
|
-
end
|
303
|
-
|
304
|
-
def concat_keys_and_values(value, max_size = nil)
|
305
|
-
return nil if value.nil?
|
306
|
-
values = Set.new
|
307
|
-
max_size = max_size.to_i if max_size
|
308
|
-
res = ''
|
309
|
-
descend(value) do |x|
|
310
|
-
next unless values.add?(x)
|
311
|
-
x = x.to_s
|
312
|
-
return res if max_size && res.size + x.size + 1 > max_size
|
313
|
-
res << "\n" unless res.empty?
|
314
|
-
res << x
|
315
|
-
end
|
316
|
-
res
|
317
|
-
end
|
318
|
-
|
319
|
-
private
|
320
|
-
|
321
|
-
def descend(value, max_iter = 1000)
|
322
|
-
seen = Set.new
|
323
|
-
look_into = [value]
|
324
|
-
idx = 0
|
325
|
-
until look_into.empty? || max_iter <= idx
|
326
|
-
idx += 1
|
327
|
-
val = look_into.pop
|
328
|
-
|
329
|
-
case val
|
330
|
-
when Hash
|
331
|
-
next unless seen.add?(val.object_id)
|
332
|
-
look_into.concat(val.keys)
|
333
|
-
look_into.concat(val.values)
|
334
|
-
when Array
|
335
|
-
next unless seen.add?(val.object_id)
|
336
|
-
look_into.concat(val)
|
337
|
-
else
|
338
|
-
next if val.respond_to?(:seek)
|
339
|
-
if val.respond_to?(:each)
|
340
|
-
next unless seen.add?(val.object_id)
|
341
|
-
val.each { |v| look_into << v }
|
342
|
-
else
|
343
|
-
yield val
|
344
|
-
end
|
345
|
-
end
|
346
|
-
end
|
347
|
-
end
|
348
|
-
end # end module Transforms
|
349
|
-
|
350
257
|
include Transforms
|
351
258
|
KNOWN_TRANSFORMS = Transforms.public_instance_methods.map(&:to_s)
|
352
259
|
|
353
260
|
def transform(value)
|
354
261
|
send(@final_transform, value, *@transform_args) if @final_transform
|
355
262
|
end
|
356
|
-
end
|
263
|
+
end
|
357
264
|
end
|