sqreen 1.18.6-java → 1.20.0-java
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 +27 -0
- data/lib/sqreen/actions.rb +2 -0
- data/lib/sqreen/actions/actions_index.rb +16 -0
- data/lib/sqreen/actions/base.rb +4 -10
- data/lib/sqreen/actions/block_ip.rb +2 -0
- data/lib/sqreen/actions/block_user.rb +2 -0
- data/lib/sqreen/actions/ip_range_indexed_action_class.rb +4 -24
- data/lib/sqreen/actions/ip_ranges_index.rb +32 -11
- data/lib/sqreen/actions/redirect_ip.rb +2 -0
- data/lib/sqreen/actions/redirect_user.rb +2 -0
- data/lib/sqreen/actions/repository.rb +27 -8
- data/lib/sqreen/actions/unknown_action_type.rb +4 -0
- data/lib/sqreen/actions/user_action_class.rb +5 -30
- data/lib/sqreen/actions/users_index.rb +35 -0
- data/lib/sqreen/agent.rb +2 -1
- data/lib/sqreen/aggregated_metric.rb +25 -0
- data/lib/sqreen/attack_blocked.rb +2 -0
- data/lib/sqreen/binding_accessor.rb +2 -0
- data/lib/sqreen/binding_accessor/path_elem.rb +2 -0
- data/lib/sqreen/binding_accessor/transforms.rb +8 -1
- data/lib/sqreen/call_countable.rb +2 -0
- data/lib/sqreen/capped_queue.rb +2 -0
- data/lib/sqreen/cb.rb +2 -0
- data/lib/sqreen/cb_tree.rb +2 -0
- data/lib/sqreen/condition_evaluator.rb +2 -0
- data/lib/sqreen/conditionable.rb +2 -0
- data/lib/sqreen/configuration.rb +19 -1
- data/lib/sqreen/context.rb +2 -0
- data/lib/sqreen/default_cb.rb +2 -0
- data/lib/sqreen/deferred_logger.rb +2 -0
- data/lib/sqreen/deliveries.rb +2 -0
- data/lib/sqreen/deliveries/batch.rb +6 -1
- data/lib/sqreen/deliveries/simple.rb +6 -0
- data/lib/sqreen/dependency.rb +3 -1
- data/lib/sqreen/dependency/detector.rb +22 -14
- data/lib/sqreen/dependency/libsqreen.rb +4 -0
- data/lib/sqreen/dependency/new_relic.rb +2 -0
- data/lib/sqreen/dependency/rack.rb +10 -5
- data/lib/sqreen/dependency/rails.rb +4 -0
- data/lib/sqreen/dependency/sentry.rb +2 -0
- data/lib/sqreen/dependency/sinatra.rb +12 -1
- data/lib/sqreen/encoding_sanitizer.rb +2 -0
- data/lib/sqreen/error_handling_middleware.rb +2 -0
- data/lib/sqreen/event.rb +9 -5
- data/lib/sqreen/events/attack.rb +25 -18
- data/lib/sqreen/events/remote_exception.rb +2 -22
- data/lib/sqreen/events/request_record.rb +17 -70
- data/lib/sqreen/exception.rb +2 -0
- data/lib/sqreen/formatter_with_tid.rb +2 -0
- data/lib/sqreen/framework_cb.rb +2 -0
- data/lib/sqreen/frameworks.rb +2 -0
- data/lib/sqreen/frameworks/generic.rb +2 -0
- data/lib/sqreen/frameworks/rails.rb +1 -0
- data/lib/sqreen/frameworks/rails3.rb +2 -0
- data/lib/sqreen/frameworks/request_recorder.rb +15 -2
- data/lib/sqreen/frameworks/sinatra.rb +2 -0
- data/lib/sqreen/frameworks/sqreen_test.rb +2 -0
- data/lib/sqreen/graft.rb +12 -0
- data/lib/sqreen/graft/call.rb +150 -0
- data/lib/sqreen/{dependency → graft}/callback.rb +12 -4
- data/lib/sqreen/graft/hook.rb +316 -0
- data/lib/sqreen/{dependency → graft}/hook_point.rb +152 -33
- data/lib/sqreen/graft/hook_point_error.rb +10 -0
- data/lib/sqreen/invalid_signature_exception.rb +2 -0
- data/lib/sqreen/js.rb +2 -0
- data/lib/sqreen/js/call_context.rb +2 -0
- data/lib/sqreen/js/context_pool.rb +2 -0
- data/lib/sqreen/js/exec_js_runnable.rb +2 -0
- data/lib/sqreen/js/execjs_adapter.rb +2 -0
- data/lib/sqreen/js/executable_js.rb +2 -0
- data/lib/sqreen/js/js_service.rb +2 -0
- data/lib/sqreen/js/js_service_adapter.rb +2 -0
- data/lib/sqreen/js/mini_racer_adapter.rb +2 -0
- data/lib/sqreen/js/mini_racer_executable_js.rb +2 -0
- data/lib/sqreen/js/thread_local_exec_js_runnable.rb +2 -0
- data/lib/sqreen/kit/signals/specialized/aggregated_metric.rb +72 -0
- data/lib/sqreen/kit/signals/specialized/attack.rb +57 -0
- data/lib/sqreen/kit/signals/specialized/binning_metric.rb +76 -0
- data/lib/sqreen/kit/signals/specialized/http_trace.rb +26 -0
- data/lib/sqreen/kit/signals/specialized/sdk_track_call.rb +50 -0
- data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +57 -0
- data/lib/sqreen/{backport.rb → legacy.rb} +3 -2
- data/lib/sqreen/{instrumentation.rb → legacy/instrumentation.rb} +31 -2
- data/lib/sqreen/legacy/old_event_submission_strategy.rb +221 -0
- data/lib/sqreen/legacy/waf_redactions.rb +49 -0
- data/lib/sqreen/log.rb +2 -0
- data/lib/sqreen/log/loggable.rb +28 -0
- data/lib/sqreen/logger.rb +2 -0
- data/lib/sqreen/metrics.rb +2 -0
- data/lib/sqreen/metrics/average.rb +2 -0
- data/lib/sqreen/metrics/base.rb +5 -0
- data/lib/sqreen/metrics/binning.rb +2 -0
- data/lib/sqreen/metrics/collect.rb +2 -0
- data/lib/sqreen/metrics/sum.rb +2 -0
- data/lib/sqreen/metrics_store.rb +24 -12
- data/lib/sqreen/metrics_store/already_registered_metric.rb +2 -0
- data/lib/sqreen/metrics_store/unknown_metric.rb +2 -0
- data/lib/sqreen/metrics_store/unregistered_metric.rb +2 -0
- data/lib/sqreen/middleware.rb +2 -0
- data/lib/sqreen/mono_time.rb +2 -0
- data/lib/sqreen/node.rb +2 -0
- data/lib/sqreen/not_implemented_yet.rb +2 -0
- data/lib/sqreen/null_logger.rb +2 -0
- data/lib/sqreen/payload_creator.rb +2 -0
- data/lib/sqreen/payload_creator/header_section.rb +2 -0
- data/lib/sqreen/performance_notifications.rb +2 -0
- data/lib/sqreen/performance_notifications/binned_metrics.rb +10 -2
- data/lib/sqreen/performance_notifications/log.rb +2 -0
- data/lib/sqreen/performance_notifications/log_performance.rb +2 -0
- data/lib/sqreen/performance_notifications/metrics.rb +2 -0
- data/lib/sqreen/performance_notifications/newrelic.rb +2 -0
- data/lib/sqreen/prefix.rb +2 -0
- data/lib/sqreen/rails_middleware.rb +2 -0
- data/lib/sqreen/remote_command.rb +2 -0
- data/lib/sqreen/remote_command/failure_output.rb +5 -0
- data/lib/sqreen/rules.rb +6 -2
- data/lib/sqreen/rules/attrs.rb +2 -0
- data/lib/sqreen/rules/auth_track_cb.rb +2 -0
- data/lib/sqreen/rules/binding_accessor_matcher_cb.rb +2 -0
- data/lib/sqreen/rules/binding_accessor_metrics.rb +2 -0
- data/lib/sqreen/rules/blacklist_ips_cb.rb +2 -0
- data/lib/sqreen/rules/count_http_codes.rb +2 -0
- data/lib/sqreen/rules/crawler_user_agent_matches_cb.rb +2 -0
- data/lib/sqreen/rules/crawler_user_agent_matches_metrics_cb.rb +2 -0
- data/lib/sqreen/rules/custom_error_cb.rb +2 -0
- data/lib/sqreen/rules/devise_auth_track_cb.rb +2 -0
- data/lib/sqreen/rules/devise_signup_track_cb.rb +2 -0
- data/lib/sqreen/rules/execjs_cb.rb +2 -0
- data/lib/sqreen/rules/headers_insert_cb.rb +7 -0
- data/lib/sqreen/rules/matcher_rule.rb +2 -0
- data/lib/sqreen/rules/not_found_cb.rb +7 -0
- data/lib/sqreen/rules/rails_parameters_cb.rb +2 -0
- data/lib/sqreen/rules/record_request_context.rb +2 -0
- data/lib/sqreen/rules/regexp_rule_cb.rb +2 -0
- data/lib/sqreen/rules/rule_cb.rb +4 -0
- data/lib/sqreen/rules/run_req_start_actions.rb +3 -1
- data/lib/sqreen/rules/run_user_actions.rb +3 -1
- data/lib/sqreen/rules/shell_env_cb.rb +2 -0
- data/lib/sqreen/rules/signup_track_cb.rb +2 -0
- data/lib/sqreen/rules/update_request_context.rb +2 -0
- data/lib/sqreen/rules/url_matches_cb.rb +2 -0
- data/lib/sqreen/rules/user_agent_matches_cb.rb +2 -0
- data/lib/sqreen/rules/waf_cb.rb +41 -16
- data/lib/sqreen/rules/xss_cb.rb +2 -0
- data/lib/sqreen/run_when_called_cb.rb +2 -0
- data/lib/sqreen/runner.rb +68 -12
- data/lib/sqreen/runtime_infos.rb +2 -0
- data/lib/sqreen/safe_json.rb +2 -0
- data/lib/sqreen/sdk.rb +4 -0
- data/lib/sqreen/sensitive_data_redactor.rb +21 -31
- data/lib/sqreen/serializer.rb +2 -0
- data/lib/sqreen/session.rb +41 -37
- data/lib/sqreen/shared_storage.rb +2 -0
- data/lib/sqreen/shared_storage23.rb +2 -0
- data/lib/sqreen/shrink_wrap.rb +16 -0
- data/lib/sqreen/signals/conversions.rb +283 -0
- data/lib/sqreen/signals/http_trace_redaction.rb +111 -0
- data/lib/sqreen/signals/signals_submission_strategy.rb +78 -0
- data/lib/sqreen/signature_verifier.rb +2 -0
- data/lib/sqreen/sinatra_middleware.rb +2 -0
- data/lib/sqreen/sqreen_signed_verifier.rb +2 -0
- data/lib/sqreen/token_invalid_exception.rb +2 -0
- data/lib/sqreen/token_not_found_exception.rb +2 -0
- data/lib/sqreen/trie.rb +2 -0
- data/lib/sqreen/unauthorized.rb +2 -0
- data/lib/sqreen/util.rb +5 -0
- data/lib/sqreen/util/capped_array.rb +2 -0
- data/lib/sqreen/util/capped_hash.rb +2 -0
- data/lib/sqreen/util/capped_string.rb +2 -0
- data/lib/sqreen/util/capper.rb +2 -0
- data/lib/sqreen/version.rb +3 -1
- data/lib/sqreen/waf_error.rb +2 -0
- data/lib/sqreen/weave.rb +12 -0
- data/lib/sqreen/weave/hardcoded.rb +19 -0
- data/lib/sqreen/weave/instrumentor.rb +48 -0
- data/lib/sqreen/weave/legacy.rb +12 -0
- data/lib/sqreen/weave/legacy/instrumentation.rb +406 -0
- data/lib/sqreen/web_server.rb +2 -0
- data/lib/sqreen/web_server/generic.rb +2 -0
- data/lib/sqreen/web_server/passenger.rb +2 -0
- data/lib/sqreen/web_server/puma.rb +2 -0
- data/lib/sqreen/web_server/rainbows.rb +2 -0
- data/lib/sqreen/web_server/thin.rb +2 -0
- data/lib/sqreen/web_server/unicorn.rb +2 -0
- data/lib/sqreen/web_server/webrick.rb +2 -0
- data/lib/sqreen/worker.rb +2 -0
- metadata +65 -9
- data/lib/sqreen/backport/original_name.rb +0 -86
- data/lib/sqreen/dependency/hook.rb +0 -102
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
# typed: ignore
|
|
2
|
+
|
|
1
3
|
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
2
4
|
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
5
|
|
|
6
|
+
require 'sqreen/legacy'
|
|
4
7
|
require 'sqreen/cb_tree'
|
|
5
8
|
require 'sqreen/log'
|
|
6
9
|
require 'sqreen/exception'
|
|
@@ -36,6 +39,8 @@ require 'set'
|
|
|
36
39
|
# end
|
|
37
40
|
|
|
38
41
|
module Sqreen
|
|
42
|
+
|
|
43
|
+
module Legacy
|
|
39
44
|
class Instrumentation
|
|
40
45
|
OVERTIME_METRIC = 'request_overtime'.freeze
|
|
41
46
|
|
|
@@ -84,6 +89,7 @@ module Sqreen
|
|
|
84
89
|
start = Sqreen.time
|
|
85
90
|
res = cb.pre(instance, args, budget, &block)
|
|
86
91
|
stop = Sqreen.time
|
|
92
|
+
Sqreen.log.debug { "ran pre cb #{cb} => #{res.inspect}" }
|
|
87
93
|
# The first few pre callbacks could not have a request & hence a budget just yet so we try harder to find it
|
|
88
94
|
budget = framework.remaining_perf_budget if framework && !budget && Sqreen.performance_budget
|
|
89
95
|
if budget
|
|
@@ -139,6 +145,7 @@ module Sqreen
|
|
|
139
145
|
start = Sqreen.time
|
|
140
146
|
res = cb.post(return_val, instance, args, budget, &block)
|
|
141
147
|
stop = Sqreen.time
|
|
148
|
+
Sqreen.log.debug { "ran post cb #{cb} => #{res.inspect}" }
|
|
142
149
|
if budget
|
|
143
150
|
budget -= (stop - start)
|
|
144
151
|
cb.overtime! if budget <= 0.0
|
|
@@ -193,6 +200,7 @@ module Sqreen
|
|
|
193
200
|
start = Sqreen.time
|
|
194
201
|
res = cb.failing(exception, instance, args, budget, &block)
|
|
195
202
|
stop = Sqreen.time
|
|
203
|
+
Sqreen.log.debug { "ran failing cb #{cb} => #{res.inspect}" }
|
|
196
204
|
if budget
|
|
197
205
|
budget -= (stop - start)
|
|
198
206
|
cb.overtime! if budget <= 0.0
|
|
@@ -508,6 +516,7 @@ module Sqreen
|
|
|
508
516
|
saved_meth_name
|
|
509
517
|
end
|
|
510
518
|
|
|
519
|
+
### bad idea anyway
|
|
511
520
|
# WARNING We do not actually remove `meth`
|
|
512
521
|
def unoverride_class_method(klass, meth)
|
|
513
522
|
saved_meth_name = get_saved_method_name(meth)
|
|
@@ -526,6 +535,7 @@ module Sqreen
|
|
|
526
535
|
end
|
|
527
536
|
end
|
|
528
537
|
|
|
538
|
+
### useless now
|
|
529
539
|
if RUBY_VERSION < '1.9'
|
|
530
540
|
def adjust_method_name(method)
|
|
531
541
|
method.to_s
|
|
@@ -554,6 +564,8 @@ module Sqreen
|
|
|
554
564
|
is_instance_method?(obj, method)
|
|
555
565
|
end
|
|
556
566
|
|
|
567
|
+
### is that actually used?
|
|
568
|
+
### if so, do not attempt to alter frozen instances
|
|
557
569
|
# Override a singleton method on an instance
|
|
558
570
|
def override_singleton_method(instance, klass_name, meth)
|
|
559
571
|
@@overriden_singleton_methods = true
|
|
@@ -647,8 +659,7 @@ module Sqreen
|
|
|
647
659
|
|
|
648
660
|
already_overriden = @@overriden_methods.include? key
|
|
649
661
|
unless already_overriden
|
|
650
|
-
Sqreen.log.debug "#{key} not
|
|
651
|
-
return
|
|
662
|
+
Sqreen.log.debug "#{key} apparently not overridden"
|
|
652
663
|
end
|
|
653
664
|
|
|
654
665
|
defined_cbs = @@registered_callbacks.get(klass, method).flatten
|
|
@@ -674,6 +685,7 @@ module Sqreen
|
|
|
674
685
|
elsif is_instance_method?(klass, method)
|
|
675
686
|
unoverride_instance_method(klass, method)
|
|
676
687
|
else
|
|
688
|
+
### Module#prepend will take care of that
|
|
677
689
|
# FIXME: Override define_method and other dynamic ways to
|
|
678
690
|
# The following should be monitored to make sure we
|
|
679
691
|
# don't forget dynamically added methods:
|
|
@@ -701,8 +713,13 @@ module Sqreen
|
|
|
701
713
|
# @return [Array<Sqreen::CB>]
|
|
702
714
|
def hardcoded_callbacks(framework)
|
|
703
715
|
[
|
|
716
|
+
### callback for performing sec responses based on ip
|
|
717
|
+
### init redefined to implement smartass way to hook it upon the
|
|
718
|
+
### framework's middleware #call
|
|
704
719
|
Sqreen::Rules::RunReqStartActions.new(framework),
|
|
720
|
+
### callback for performing sec responses based on user
|
|
705
721
|
Sqreen::Rules::RunUserActions.new(Sqreen, :identify, 0),
|
|
722
|
+
### callback for performing sec responses based on user
|
|
706
723
|
Sqreen::Rules::RunUserActions.new(Sqreen, :auth_track, 1),
|
|
707
724
|
]
|
|
708
725
|
end
|
|
@@ -711,6 +728,7 @@ module Sqreen
|
|
|
711
728
|
# @param rules [Array<Hash>] Rules to instrument
|
|
712
729
|
# @param framework [Sqreen::Frameworks::GenericFramework]
|
|
713
730
|
def instrument!(rules, framework)
|
|
731
|
+
### set up rule signature verifier
|
|
714
732
|
verifier = nil
|
|
715
733
|
if Sqreen.features['rules_signature'] &&
|
|
716
734
|
Sqreen.config_get(:rules_verify_signature) == true &&
|
|
@@ -720,33 +738,44 @@ module Sqreen
|
|
|
720
738
|
Sqreen.log.debug('Rules signature is not enabled')
|
|
721
739
|
end
|
|
722
740
|
|
|
741
|
+
### force clean instrumentation callback list
|
|
723
742
|
remove_all_callbacks # Force cb tree to be empty before instrumenting
|
|
724
743
|
|
|
744
|
+
### for each rule description, transform into format for adding callback
|
|
725
745
|
rules.each do |rule|
|
|
726
746
|
rcb = Sqreen::Rules.cb_from_rule(rule, self, metrics_engine, verifier)
|
|
727
747
|
next unless rcb
|
|
748
|
+
### attach framework to callback
|
|
728
749
|
rcb.framework = framework
|
|
750
|
+
### add callback
|
|
729
751
|
add_callback(rcb)
|
|
730
752
|
end
|
|
731
753
|
|
|
732
754
|
# add hardcoded callbacks, observing priority
|
|
733
755
|
hardcoded_callbacks(framework).each { |cb| add_callback(cb) }
|
|
734
756
|
|
|
757
|
+
### globally declare instrumentation ready
|
|
758
|
+
### from within instance method? not even thread local?
|
|
735
759
|
Sqreen.instrumentation_ready = true
|
|
736
760
|
end
|
|
737
761
|
|
|
738
762
|
def initialize(metrics_engine = nil)
|
|
739
763
|
self.metrics_engine = metrics_engine
|
|
740
764
|
return if metrics_engine.nil?
|
|
765
|
+
### init metric to count calls to sqreen
|
|
741
766
|
metrics_engine.create_metric('name' => CallCountable::COUNT_CALLS,
|
|
742
767
|
'period' => 60,
|
|
743
768
|
'kind' => 'Sum')
|
|
769
|
+
### init metric to count request whitelist matches (ip or path whitelist)
|
|
744
770
|
metrics_engine.create_metric('name' => Sqreen::Rules::RecordRequestContext::WHITELISTED_METRIC,
|
|
745
771
|
'period' => 60,
|
|
746
772
|
'kind' => 'Sum')
|
|
773
|
+
### init metric to count over budget hits
|
|
747
774
|
metrics_engine.create_metric('name' => OVERTIME_METRIC,
|
|
748
775
|
'period' => 60,
|
|
749
776
|
'kind' => 'Sum')
|
|
750
777
|
end
|
|
751
778
|
end
|
|
752
779
|
end
|
|
780
|
+
|
|
781
|
+
end
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# typed: ignore
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'sqreen/aggregated_metric'
|
|
7
|
+
require 'sqreen/log/loggable'
|
|
8
|
+
require 'sqreen/legacy/waf_redactions'
|
|
9
|
+
|
|
10
|
+
module Sqreen
|
|
11
|
+
module Legacy
|
|
12
|
+
# see also Sqreen::Signals::SignalsSubmissionStrategy
|
|
13
|
+
# usage in Sqreen:Session
|
|
14
|
+
class OldEventSubmissionStrategy
|
|
15
|
+
include Sqreen::Log::Loggable
|
|
16
|
+
|
|
17
|
+
RETRY_MANY = 301
|
|
18
|
+
|
|
19
|
+
def initialize(post_proc)
|
|
20
|
+
@post_proc = post_proc
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def post_metrics(metrics)
|
|
24
|
+
return if metrics.nil? || metrics.empty?
|
|
25
|
+
payload = { metrics: metrics.map { |m| EventToHash.convert_agg_metric(m) } }
|
|
26
|
+
post('metrics', payload, {}, RETRY_MANY)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @param attack [Sqreen::Attack]
|
|
30
|
+
def post_attack(attack)
|
|
31
|
+
post('attack', EventToHash.convert_attack(attack), {}, RETRY_MANY)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @param [Sqreen::RequestRecord] request_record
|
|
35
|
+
def post_request_record(request_record)
|
|
36
|
+
rr_hash = EventToHash.convert_request_record(request_record)
|
|
37
|
+
post('request_record', rr_hash, {}, RETRY_MANY)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Post an exception to Sqreen for analysis
|
|
41
|
+
# @param exception [RemoteException] Exception and context to be sent over
|
|
42
|
+
def post_sqreen_exception(exception)
|
|
43
|
+
data = EventToHash.convert_exception(exception)
|
|
44
|
+
post('sqreen_exception', data, {}, 5)
|
|
45
|
+
rescue StandardError => e
|
|
46
|
+
logger.warn(format('Could not post exception (network down? %s) %s',
|
|
47
|
+
e.inspect,
|
|
48
|
+
exception.inspect))
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def post_batch(events)
|
|
53
|
+
batch = events.map do |event|
|
|
54
|
+
h = case event
|
|
55
|
+
when AggregatedMetric
|
|
56
|
+
logger.warn "Aggregated metric event in non-signal mode. Signals disabled at runtime?"
|
|
57
|
+
next
|
|
58
|
+
when Attack # in practice only found inside req rec
|
|
59
|
+
EventToHash.convert_attack event
|
|
60
|
+
when RemoteException
|
|
61
|
+
EventToHash.convert_exception event
|
|
62
|
+
when RequestRecord
|
|
63
|
+
EventToHash.convert_request_record event
|
|
64
|
+
else
|
|
65
|
+
logger.warn "Unexpected event type: #{event}"
|
|
66
|
+
next
|
|
67
|
+
end
|
|
68
|
+
h['event_type'] = event_kind(event)
|
|
69
|
+
h
|
|
70
|
+
end
|
|
71
|
+
Sqreen.log.debug do
|
|
72
|
+
tally = Hash[events.group_by(&:class).map { |k, v| [k, v.count] }]
|
|
73
|
+
"Doing batch with the following tally of event types: #{tally}"
|
|
74
|
+
end
|
|
75
|
+
post('batch', { batch: batch }, {}, RETRY_MANY)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
# see +Sqreen::Session.post+
|
|
81
|
+
def post(*args)
|
|
82
|
+
@post_proc[*args]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def event_kind(event)
|
|
86
|
+
case event
|
|
87
|
+
when Sqreen::RemoteException then 'sqreen_exception'
|
|
88
|
+
when Sqreen::Attack then 'attack'
|
|
89
|
+
when Sqreen::RequestRecord then 'request_record'
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
module EventToHash
|
|
95
|
+
class << self
|
|
96
|
+
# @param attack [Sqreen::Attack]
|
|
97
|
+
def convert_attack(attack)
|
|
98
|
+
payload = attack.payload
|
|
99
|
+
res = {}
|
|
100
|
+
rule_p = payload['rule']
|
|
101
|
+
request_p = payload['request']
|
|
102
|
+
res[:rule_name] = rule_p['name'] if rule_p && rule_p['name']
|
|
103
|
+
res[:rulespack_id] = rule_p['rulespack_id'] if rule_p && rule_p['rulespack_id']
|
|
104
|
+
res[:test] = rule_p['test'] if rule_p && rule_p['test']
|
|
105
|
+
res[:infos] = payload['infos'] if payload['infos']
|
|
106
|
+
res[:time] = attack.time
|
|
107
|
+
res[:client_ip] = request_p[:addr] if request_p && request_p[:addr]
|
|
108
|
+
res[:request] = request_p if request_p
|
|
109
|
+
res[:params] = payload['params'] if payload['params']
|
|
110
|
+
res[:context] = payload['context'] if payload['context']
|
|
111
|
+
res[:headers] = payload['headers'] if payload['headers']
|
|
112
|
+
res
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @param [Sqreen::RequestRecord] rr
|
|
116
|
+
def convert_request_record(rr)
|
|
117
|
+
res = { :version => '20171208' }
|
|
118
|
+
payload = rr.payload
|
|
119
|
+
|
|
120
|
+
if payload[:observed]
|
|
121
|
+
res[:observed] = payload[:observed].dup
|
|
122
|
+
rulespack = nil
|
|
123
|
+
if rr.observed[:attacks]
|
|
124
|
+
res[:observed][:attacks] = rr.observed[:attacks].map do |att|
|
|
125
|
+
natt = att.dup
|
|
126
|
+
[:attack_type, :block].each { |k| natt.delete(k) } # signals stuff
|
|
127
|
+
rulespack = natt.delete(:rulespack_id) || rulespack
|
|
128
|
+
natt
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
if rr.observed[:sqreen_exceptions]
|
|
132
|
+
res[:observed][:sqreen_exceptions] = rr.observed[:sqreen_exceptions].map do |exc|
|
|
133
|
+
nex = exc.dup
|
|
134
|
+
excp = nex.delete(:exception)
|
|
135
|
+
if excp
|
|
136
|
+
nex[:message] = excp.message
|
|
137
|
+
nex[:klass] = excp.class.name
|
|
138
|
+
end
|
|
139
|
+
rulespack = nex.delete(:rulespack_id) || rulespack
|
|
140
|
+
nex
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
res[:rulespack_id] = rulespack unless rulespack.nil?
|
|
144
|
+
if rr.observed[:observations]
|
|
145
|
+
res[:observed][:observations] = rr.observed[:observations].map do |cat, key, value, time|
|
|
146
|
+
{ :category => cat, :key => key, :value => value, :time => time }
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
if rr.observed[:sdk] # rubocop:disable Style/IfUnlessModifier
|
|
150
|
+
res[:observed][:sdk] = rr.processed_sdk_calls
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
res[:local] = payload['local'] if payload['local']
|
|
154
|
+
if payload['request']
|
|
155
|
+
res[:request] = payload['request'].dup
|
|
156
|
+
res[:client_ip] = res[:request].delete(:client_ip) if res[:request][:client_ip]
|
|
157
|
+
else
|
|
158
|
+
res[:request] = {}
|
|
159
|
+
end
|
|
160
|
+
if payload['response']
|
|
161
|
+
res[:response] = payload['response'].dup
|
|
162
|
+
else
|
|
163
|
+
res[:response] = {}
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
res[:request][:parameters] = payload['params'] if payload['params']
|
|
167
|
+
res[:request][:headers] = payload['headers'] if payload['headers']
|
|
168
|
+
|
|
169
|
+
res = Sqreen::EncodingSanitizer.sanitize(res)
|
|
170
|
+
|
|
171
|
+
if rr.redactor
|
|
172
|
+
res[:request], redacted = rr.redactor.redact(res[:request])
|
|
173
|
+
redacted = redacted.uniq
|
|
174
|
+
if redacted.any? && res[:observed] && res[:observed][:attacks]
|
|
175
|
+
res[:observed][:attacks] = WafRedactions.redact_attacks!(res[:observed][:attacks], redacted)
|
|
176
|
+
end
|
|
177
|
+
if redacted.any? && res[:observed] && res[:observed][:sqreen_exceptions]
|
|
178
|
+
res[:observed][:sqreen_exceptions] = WafRedactions.redact_exceptions!(res[:observed][:sqreen_exceptions], redacted)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
res
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# @param exception_evt [Sqreen::RemoteException]
|
|
186
|
+
def convert_exception(exception_evt)
|
|
187
|
+
payload = exception_evt.payload
|
|
188
|
+
exception = payload['exception']
|
|
189
|
+
ev = {
|
|
190
|
+
:klass => exception.class.name,
|
|
191
|
+
:message => exception.message,
|
|
192
|
+
:params => payload['request_params'],
|
|
193
|
+
:time => payload['time'],
|
|
194
|
+
:infos => {
|
|
195
|
+
:client_ip => payload['client_ip'],
|
|
196
|
+
},
|
|
197
|
+
:request => payload['request_infos'],
|
|
198
|
+
:headers => payload['headers'],
|
|
199
|
+
:rule_name => payload['rule_name'],
|
|
200
|
+
:rulespack_id => payload['rulespack_id'],
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
ev[:infos].merge!(payload['infos']) if payload['infos']
|
|
204
|
+
return ev unless exception.backtrace
|
|
205
|
+
ev[:context] = { :backtrace => exception.backtrace.map(&:to_s) }
|
|
206
|
+
ev
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# @param [Sqreen::AggregatedMetric] agg_metric
|
|
210
|
+
def convert_agg_metric(agg_metric)
|
|
211
|
+
{
|
|
212
|
+
name: agg_metric.name,
|
|
213
|
+
observation: agg_metric.data,
|
|
214
|
+
start: agg_metric.start,
|
|
215
|
+
finish: agg_metric.finish,
|
|
216
|
+
}
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# typed: ignore
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
module Sqreen
|
|
7
|
+
module Legacy
|
|
8
|
+
module WafRedactions
|
|
9
|
+
class << self
|
|
10
|
+
def redact_attacks!(attacks, values)
|
|
11
|
+
return attacks if values.empty?
|
|
12
|
+
|
|
13
|
+
values = values.map { |v| v.downcase if v.is_a?(String) }
|
|
14
|
+
|
|
15
|
+
attacks.each do |e|
|
|
16
|
+
next(e) unless e[:infos]
|
|
17
|
+
next(e) unless e[:infos][:waf_data]
|
|
18
|
+
|
|
19
|
+
parsed = JSON.parse(e[:infos][:waf_data])
|
|
20
|
+
redacted = parsed.each do |w|
|
|
21
|
+
next unless (filters = w['filter'])
|
|
22
|
+
|
|
23
|
+
filters.each do |f|
|
|
24
|
+
next unless (v = f['resolved_value'])
|
|
25
|
+
next unless values.include?(v.downcase)
|
|
26
|
+
|
|
27
|
+
f['match_status'] = SensitiveDataRedactor::MASK
|
|
28
|
+
f['resolved_value'] = SensitiveDataRedactor::MASK
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
e[:infos][:waf_data] = JSON.dump(redacted)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# see https://github.com/sqreen/TechDoc/blob/master/content/specs/spec000022-waf-data-sanitization.md#changes-to-the-agents
|
|
36
|
+
def redact_exceptions!(exceptions, values)
|
|
37
|
+
return exceptions if values.empty?
|
|
38
|
+
|
|
39
|
+
exceptions.each do |e|
|
|
40
|
+
next(e) unless e[:infos]
|
|
41
|
+
next(e) unless e[:infos][:waf]
|
|
42
|
+
|
|
43
|
+
e[:infos][:waf].delete(:args)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
data/lib/sqreen/log.rb
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'logger'
|
|
7
|
+
|
|
8
|
+
module Sqreen; end
|
|
9
|
+
module Sqreen::Log; end
|
|
10
|
+
|
|
11
|
+
module Sqreen::Log::Loggable
|
|
12
|
+
def self.included(klass)
|
|
13
|
+
klass.extend(ClassMethods)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module ClassMethods
|
|
17
|
+
def logger
|
|
18
|
+
# TODO: use progname for qualified log messages
|
|
19
|
+
# TODO: qualified logger proxies for selectable levels per component
|
|
20
|
+
# @logger ||= ::Logger.new(STDOUT, progname: name, level: Logger::DEBUG)
|
|
21
|
+
Sqreen.log
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def logger
|
|
26
|
+
@logger || self.class.logger
|
|
27
|
+
end
|
|
28
|
+
end
|