tcell_agent 0.2.10 → 0.2.11
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/lib/tcell_agent/configuration.rb +75 -10
- data/lib/tcell_agent/instrumentation.rb +3 -0
- data/lib/tcell_agent/logger.rb +2 -2
- data/lib/tcell_agent/rails/dlp.rb +82 -43
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +5 -4
- data/lib/tcell_agent/sensor_events/app_sensor.rb +44 -2
- data/lib/tcell_agent/servers/puma.rb +7 -2
- data/lib/tcell_agent/version.rb +1 -1
- data/spec/lib/tcell_agent/agent/policy_manager_spec.rb +1 -1
- data/spec/lib/tcell_agent/configuration_spec.rb +371 -0
- data/spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb +7 -7
- data/spec/lib/tcell_agent/sensor_events/tcell_app_sensor_event_processor_spec.rb +289 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d554725aca1909bfd60fe8c8eaea0a31d9f81db4
|
4
|
+
data.tar.gz: 49d5a1f379e3fe812f705bf8455574d14c5af44c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba72d99a1a9d4b280010f35ef9c748baa8127445afe5a24f717819a3e10655d5a179a055bf777a2f492d2114fb4a05bfad4f34f597e322085426bfc70e2720bc
|
7
|
+
data.tar.gz: d9a76ef1c4ba6037d6f13bb43fbf01895d29e625da2cc3174767e1cf1edee54d9ee4bfe2bd55441fe3587ce21db40a578a1156566cd98f6f2982d8be40bf7689
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# See the file "LICENSE" for the full license governing this code.
|
2
2
|
require 'fileutils'
|
3
3
|
require 'json'
|
4
|
+
require 'yaml'
|
4
5
|
require 'socket'
|
5
6
|
require 'securerandom'
|
6
7
|
|
@@ -15,7 +16,7 @@ module TCellAgent
|
|
15
16
|
end
|
16
17
|
|
17
18
|
class Configuration
|
18
|
-
attr_accessor :version, :app_id, :api_key, :hmac_key,
|
19
|
+
attr_accessor :version, :app_id, :api_key, :hmac_key,
|
19
20
|
:tcell_api_url, :tcell_input_url,
|
20
21
|
:logging_options,
|
21
22
|
:fetch_policies_from_tcell, :instrument_for_events,
|
@@ -25,13 +26,18 @@ module TCellAgent
|
|
25
26
|
:uuid,
|
26
27
|
:company,
|
27
28
|
:event_batch_size_limit, :event_time_limit_seconds,
|
28
|
-
:
|
29
|
+
:log_filename,
|
29
30
|
:base_dir,
|
30
31
|
:cache_filename,
|
31
32
|
:js_agent_api_base_url,
|
32
33
|
:js_agent_url,
|
33
34
|
:raise_exceptions,
|
34
|
-
:allow_unencrypted_appsensor_payloads
|
35
|
+
:allow_unencrypted_appsensor_payloads,
|
36
|
+
:blacklisted_params,
|
37
|
+
:whitelisted_params,
|
38
|
+
:whitelist_present,
|
39
|
+
:config_filename,
|
40
|
+
:max_data_ex_db_records_per_request
|
35
41
|
|
36
42
|
attr_accessor :disable_all,
|
37
43
|
:enabled,
|
@@ -79,16 +85,23 @@ module TCellAgent
|
|
79
85
|
@enable_instrumentation = true
|
80
86
|
@enable_intercept_requests = true
|
81
87
|
|
82
|
-
|
83
|
-
@
|
88
|
+
|
89
|
+
@agent_home_dir = File.join(Dir.getwd, "tcell")
|
90
|
+
@agent_log_dir = File.join(@agent_home_dir, "logs")
|
91
|
+
@config_filename = File.join(Dir.getwd, filename)
|
84
92
|
|
85
93
|
@event_batch_size_limit = 50
|
86
94
|
@event_time_limit_seconds = 15
|
87
95
|
|
88
96
|
@raise_exceptions = false
|
89
97
|
|
98
|
+
@max_data_ex_db_records_per_request = 1000
|
99
|
+
|
90
100
|
read_config_using_env
|
91
|
-
read_config_from_file(
|
101
|
+
read_config_from_file(@config_filename)
|
102
|
+
|
103
|
+
@cache_filename = File.join(@agent_home_dir, "cache", "tcell_agent.cache")
|
104
|
+
@log_filename = File.join(@agent_log_dir, "tcell_agent.log")
|
92
105
|
|
93
106
|
# Because ENV can override this one
|
94
107
|
env_unencrypted_firewall =
|
@@ -115,11 +128,13 @@ module TCellAgent
|
|
115
128
|
@uuid = SecureRandom.uuid
|
116
129
|
|
117
130
|
FileUtils::mkdir_p File.dirname(@cache_filename)
|
118
|
-
if @logging_options
|
131
|
+
if @logging_options && @logging_options["filename"]
|
119
132
|
FileUtils::mkdir_p File.dirname(@logging_options["filename"])
|
120
133
|
else
|
121
|
-
FileUtils::mkdir_p File.dirname(@
|
134
|
+
FileUtils::mkdir_p File.dirname(@log_filename)
|
122
135
|
end
|
136
|
+
|
137
|
+
load_app_sensor_restrictions
|
123
138
|
end
|
124
139
|
|
125
140
|
def cache_filename_with_app_id
|
@@ -139,6 +154,10 @@ module TCellAgent
|
|
139
154
|
@tcell_input_url = ENV["TCELL_INPUT_URL"]
|
140
155
|
@demomode = ENV["TCELL_DEMOMODE"] || @demomode
|
141
156
|
|
157
|
+
@agent_home_dir = ENV["TCELL_AGENT_HOME"] || @agent_home_dir
|
158
|
+
@agent_log_dir = ENV["TCELL_AGENT_LOG_DIR"] || File.join(@agent_home_dir, "logs")
|
159
|
+
@config_filename = ENV["TCELL_AGENT_CONFIG"] || @config_filename
|
160
|
+
|
142
161
|
if @demomode
|
143
162
|
@event_batch_size_limit = 2
|
144
163
|
@event_time_limit_seconds = 5
|
@@ -151,7 +170,7 @@ module TCellAgent
|
|
151
170
|
if File.file?(filename)
|
152
171
|
#puts "tCell.io: Loading from file"
|
153
172
|
begin
|
154
|
-
config_text = open(filename).read
|
173
|
+
config_text = File.open(filename).read
|
155
174
|
config = JSON.parse(config_text)
|
156
175
|
if (config["version"] == 1)
|
157
176
|
# Required
|
@@ -189,6 +208,8 @@ module TCellAgent
|
|
189
208
|
@allow_unencrypted_appsensor_payloads = app_data.fetch('allow_unencrypted_appsensor_payloads', @allow_unencrypted_appsensor_payloads)
|
190
209
|
@allow_unencrypted_appsensor_payloads = app_data.fetch('allow_unencrypted_appfirewall_payloads', @allow_unencrypted_appsensor_payloads)
|
191
210
|
|
211
|
+
data_exposure = app_data.fetch('data_exposure', {})
|
212
|
+
@max_data_ex_db_records_per_request = data_exposure.fetch('max_data_ex_db_records_per_request', @max_data_ex_db_records_per_request)
|
192
213
|
|
193
214
|
@host_identifier = @host_identifier || app_data.fetch("host_identifier", @host_identifier)
|
194
215
|
if (@host_identifier == nil)
|
@@ -218,7 +239,7 @@ module TCellAgent
|
|
218
239
|
@event_batch_size_limit = 2
|
219
240
|
@event_time_limit_seconds = 5
|
220
241
|
end
|
221
|
-
else
|
242
|
+
else
|
222
243
|
puts " ********* ********* ********* *********"
|
223
244
|
puts "* tCell.io *"
|
224
245
|
puts "* Unsupported config file version *"
|
@@ -233,6 +254,50 @@ module TCellAgent
|
|
233
254
|
end #begin
|
234
255
|
end # filename exist
|
235
256
|
end #def read
|
257
|
+
|
258
|
+
def load_app_sensor_restrictions
|
259
|
+
payloads_config_filename = ENV["TCELL_AGENT_PAYLOADS_CONFIG"] || "config/tcell_agent_payloads.config"
|
260
|
+
|
261
|
+
@blacklisted_params = {
|
262
|
+
"token" => true,
|
263
|
+
"client_secret" => true,
|
264
|
+
"password" => true,
|
265
|
+
"passwd" => true,
|
266
|
+
"refresh_token" => true,
|
267
|
+
"pf.pass" => true,
|
268
|
+
"user.password" => true
|
269
|
+
}
|
270
|
+
@whitelisted_params = {}
|
271
|
+
@whitelist_present = false
|
272
|
+
|
273
|
+
if File.file?(payloads_config_filename)
|
274
|
+
begin
|
275
|
+
payloads_config = YAML.load(File.open(payloads_config_filename).read)
|
276
|
+
if payloads_config.has_key?("blacklisted")
|
277
|
+
@blacklisted_params = {}
|
278
|
+
payloads_config["blacklisted"].each do |param_name|
|
279
|
+
@blacklisted_params[param_name.downcase] = true
|
280
|
+
end
|
281
|
+
end
|
282
|
+
if payloads_config.has_key?("whitelisted")
|
283
|
+
@whitelist_present = true
|
284
|
+
payloads_config["whitelisted"].each do |param_name|
|
285
|
+
@whitelisted_params[param_name.downcase] = true
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
rescue Exception => e
|
290
|
+
@allow_unencrypted_appsensor_payloads = false
|
291
|
+
|
292
|
+
puts " ********* ********* ********* **********"
|
293
|
+
puts "* tCell.io *"
|
294
|
+
puts "* Could not load payloads config file *"
|
295
|
+
puts " ********* ********* ********* **********"
|
296
|
+
puts e
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
236
301
|
end # class
|
237
302
|
|
238
303
|
TCellAgent.configuration ||= TCellAgent::Configuration.new
|
@@ -5,6 +5,7 @@ require 'tcell_agent/logger'
|
|
5
5
|
require 'tcell_agent/configuration'
|
6
6
|
require 'tcell_agent/version'
|
7
7
|
require 'date'
|
8
|
+
require 'cgi'
|
8
9
|
|
9
10
|
module TCellAgent
|
10
11
|
module Instrumentation
|
@@ -126,6 +127,7 @@ module TCellAgent
|
|
126
127
|
session_id_actions.action_id
|
127
128
|
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
128
129
|
)
|
130
|
+
|
129
131
|
end
|
130
132
|
end
|
131
133
|
end
|
@@ -133,6 +135,7 @@ module TCellAgent
|
|
133
135
|
replace_filters = (context_filters.select {|context_filter| context_filter.rule.body_redact == true })
|
134
136
|
event_filters = (context_filters.select {|context_filter| (context_filter.rule.body_redact != true && context_filter.rule.body_event == true) })
|
135
137
|
send_flag = TCellData.filterx(body, event_filters.length > 0, replace_filters.length > 0, term)
|
138
|
+
send_flag = send_flag || TCellData.filterx(body, event_filters.length > 0, replace_filters.length > 0, CGI.escapeHTML(term))
|
136
139
|
if send_flag
|
137
140
|
(replace_filters + event_filters).each { |filter|
|
138
141
|
base_event = TCellAgent::SensorEvents::DlpEvent.new(
|
data/lib/tcell_agent/logger.rb
CHANGED
@@ -34,7 +34,7 @@ module TCellAgent
|
|
34
34
|
if logging_options && logging_options["enabled"]
|
35
35
|
FileUtils.mkdir_p 'tcell/logs'
|
36
36
|
level = loggingLevelFromString(logging_options["level"])
|
37
|
-
logging_file = logging_options["filename"] || TCellAgent.configuration.
|
37
|
+
logging_file = logging_options["filename"] || TCellAgent.configuration.log_filename
|
38
38
|
# limit the total log file to about 9 * 5 = 45 mb
|
39
39
|
@logger = Logger.new(logging_file, shift_age=9, shift_size=5242880)
|
40
40
|
@logger.level = level
|
@@ -47,7 +47,7 @@ module TCellAgent
|
|
47
47
|
return @logger
|
48
48
|
end
|
49
49
|
|
50
|
-
logger = Logger.new(TCellAgent.configuration.
|
50
|
+
logger = Logger.new(TCellAgent.configuration.log_filename)
|
51
51
|
logger.level = Logger::ERROR
|
52
52
|
return logger
|
53
53
|
end
|
@@ -51,58 +51,97 @@ require 'thread'
|
|
51
51
|
require 'tcell_agent/configuration'
|
52
52
|
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
54
|
+
module TCellAgent
|
55
|
+
class MyRailtie < Rails::Railtie
|
56
|
+
initializer 'activeservice.autoload', :after => :set_autoload_paths do |app|
|
57
|
+
|
58
|
+
if defined?(ActiveRecord)
|
59
|
+
ActiveRecord::Relation.class_eval do
|
60
|
+
|
61
|
+
alias_method :original_exec_queries, :exec_queries
|
62
|
+
def exec_queries
|
63
|
+
@records = original_exec_queries
|
64
|
+
|
65
|
+
TCellAgent::Instrumentation.safe_block("Running DLP on query") do
|
66
|
+
if @records.size > 0
|
67
|
+
|
68
|
+
if TCellAgent.configuration.enabled &&
|
69
|
+
TCellAgent.configuration.should_instrument? &&
|
70
|
+
TCellAgent.configuration.should_intercept_requests?
|
71
|
+
|
72
|
+
dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DataLoss)
|
73
|
+
|
74
|
+
if dlp_policy
|
75
|
+
request_env = TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS.fetch(Thread.current.object_id, nil)
|
76
|
+
|
77
|
+
if request_env
|
78
|
+
tcell_context = request_env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID]
|
79
|
+
|
80
|
+
if tcell_context
|
81
|
+
first_record = @records.first
|
82
|
+
database_name = first_record.class.connection_config().fetch(:database,"*").split('/').last
|
83
|
+
model = first_record.class
|
84
|
+
column_names = model.columns.map { |col| col.name }
|
85
|
+
table_name = model.table_name
|
86
|
+
|
87
|
+
if dlp_policy.database_discovery_enabled
|
88
|
+
TCellAgent.discover_database_fields(
|
89
|
+
tcell_context.route_id,
|
90
|
+
database_name,
|
91
|
+
"*",
|
92
|
+
table_name,
|
93
|
+
column_names
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
column_name_to_rules = first_record.attributes.keys.inject({}) do |memo, column_name|
|
98
|
+
memo[column_name] = dlp_policy.get_actions_for_table(
|
99
|
+
database_name,
|
100
|
+
"*",
|
101
|
+
table_name,
|
102
|
+
column_name,
|
103
|
+
tcell_context.route_id
|
104
|
+
)
|
105
|
+
|
106
|
+
memo
|
107
|
+
end
|
108
|
+
|
109
|
+
if @records.size > TCellAgent.configuration.max_data_ex_db_records_per_request
|
110
|
+
TCellAgent.logger.warn("Route (#{tcell_context.route_id}) retrieved too many records")
|
111
|
+
end
|
112
|
+
|
113
|
+
@records[0...TCellAgent.configuration.max_data_ex_db_records_per_request].each do |record|
|
114
|
+
column_name_to_rules.each do |column_name, rules|
|
115
|
+
if rules
|
116
|
+
rules.each do |rule|
|
117
|
+
tcell_context.add_response_db_filter(
|
118
|
+
record[column_name.to_sym],
|
119
|
+
rule,
|
120
|
+
database_name,
|
121
|
+
"*",
|
122
|
+
table_name,
|
123
|
+
column_name
|
124
|
+
)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
92
131
|
end
|
93
132
|
end
|
94
133
|
end
|
95
134
|
end
|
135
|
+
|
136
|
+
@records
|
96
137
|
end
|
97
|
-
end # /if dlp_policy
|
98
|
-
end # /enabled
|
99
|
-
end # /after_find
|
100
|
-
end # /class
|
101
|
-
end
|
102
138
|
|
139
|
+
end
|
103
140
|
end
|
141
|
+
|
104
142
|
end
|
105
143
|
end
|
144
|
+
end
|
106
145
|
|
107
146
|
|
108
147
|
|
@@ -145,18 +145,19 @@ module TCellAgent
|
|
145
145
|
rack_response = Rack::Response.new(response)
|
146
146
|
|
147
147
|
if appsensor_policy && appsensor_policy.enabled
|
148
|
-
event = TCellAgent::SensorEvents::TCellAppSensorEventProcessor.new
|
148
|
+
event = TCellAgent::SensorEvents::TCellAppSensorEventProcessor.new
|
149
149
|
event.request_headers = request.env
|
150
150
|
event.request_content_length = (request.content_length || "0").to_i
|
151
151
|
event.response_content_length = (rack_response.length || "0").to_i
|
152
|
+
event.request_content_type = request.content_type
|
152
153
|
event.remote_addr = request.ip
|
153
|
-
event.uri = request.fullpath
|
154
|
+
event.uri = "#{request.base_url}#{request.fullpath}"
|
154
155
|
event.get_params = request.GET
|
155
156
|
event.post_params = request.POST
|
157
|
+
event.request_body = request.body.gets
|
156
158
|
event.cookies = request.cookies
|
157
159
|
event.request_method = request.request_method
|
158
|
-
|
159
|
-
request_body = request.body
|
160
|
+
|
160
161
|
event.request_size = event.request_content_length
|
161
162
|
#status, headers, active_response = response
|
162
163
|
#if active_response.class != ActionDispatch::Response
|
@@ -54,20 +54,33 @@ module TCellAgent
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
class TCellAppSensorEventProcessor < TCellSensorEvent
|
57
|
-
attr_accessor :request_headers, :request_size, :remote_addr,
|
57
|
+
attr_accessor :request_headers, :request_size, :remote_addr,
|
58
58
|
:uri, :get_params, :post_params, :cookies,
|
59
59
|
:request_content_length, :request_content_type,
|
60
|
-
:request_method
|
60
|
+
:request_method, :request_body
|
61
61
|
attr_accessor :status_code, :response_headers,
|
62
62
|
:response_content_length,
|
63
63
|
:route_id, :transaction_id, :session_id, :user_id
|
64
|
+
|
64
65
|
def initialize
|
65
66
|
@request_content_length=0
|
66
67
|
@response_content_length = 0
|
67
68
|
@send = false
|
69
|
+
@body_params = nil
|
68
70
|
end
|
71
|
+
|
69
72
|
def appsensor_event(dp, param, data, payload=nil)
|
70
73
|
TCellAgent::Instrumentation.safe_block("AppSensor Sending Event") {
|
74
|
+
unless payload.nil?
|
75
|
+
if TCellAgent.configuration.blacklisted_params.has_key?(param.downcase)
|
76
|
+
payload = "BLACKLISTED"
|
77
|
+
|
78
|
+
elsif TCellAgent.configuration.whitelist_present &&
|
79
|
+
!TCellAgent.configuration.whitelisted_params.has_key?(param.downcase)
|
80
|
+
payload = "NOT_WHITELISTED"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
71
84
|
event = TCellAgent::SensorEvents::TCellAppSensorEvent.new(
|
72
85
|
@uri,
|
73
86
|
dp,
|
@@ -84,6 +97,7 @@ module TCellAgent
|
|
84
97
|
TCellAgent.send_event(event)
|
85
98
|
}
|
86
99
|
end
|
100
|
+
|
87
101
|
def loop_params_hash(method, param_hash, prefix, &block)
|
88
102
|
param_hash.each do |param_name, param_value|
|
89
103
|
if param_value && param_value.is_a?(Hash)
|
@@ -95,6 +109,7 @@ module TCellAgent
|
|
95
109
|
end
|
96
110
|
end
|
97
111
|
end
|
112
|
+
|
98
113
|
def for_params(&block)
|
99
114
|
if @get_params
|
100
115
|
self.loop_params_hash('get', @get_params, nil, &block)
|
@@ -102,13 +117,40 @@ module TCellAgent
|
|
102
117
|
if @post_params
|
103
118
|
self.loop_params_hash('post', @post_params, nil, &block)
|
104
119
|
end
|
120
|
+
if body_params.length > 0
|
121
|
+
self.loop_params_hash('body', body_params, nil, &block)
|
122
|
+
end
|
105
123
|
end
|
124
|
+
|
106
125
|
def for_get_params(&block)
|
107
126
|
if @get_params
|
108
127
|
self.loop_params_hash('get', @get_params, nil, &block)
|
109
128
|
end
|
110
129
|
end
|
111
130
|
|
131
|
+
def body_params
|
132
|
+
if @body_params
|
133
|
+
@body_params
|
134
|
+
|
135
|
+
elsif @request_content_length > 2000000
|
136
|
+
@body_params = {}
|
137
|
+
|
138
|
+
else
|
139
|
+
if @request_content_type =~ %r{application/json}i && @request_body
|
140
|
+
begin
|
141
|
+
@body_params = JSON.parse(@request_body)
|
142
|
+
rescue
|
143
|
+
TCellAgent.logger.debug("JSON body parameter parsing failed")
|
144
|
+
@body_params = {}
|
145
|
+
end
|
146
|
+
else
|
147
|
+
@body_params = {}
|
148
|
+
end
|
149
|
+
|
150
|
+
@body_params
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
112
154
|
def test_response_size
|
113
155
|
if (@response_content_length && @response_content_length > TCellAgent::Policies::AppSensorPolicy::MAX_NORMAL_RESPONSE_BYTES)
|
114
156
|
appsensor_event(TCellAgent::Policies::AppSensorPolicy::DP_UNUSUAL_RESPONSE_SIZE, response_content_length.to_s, nil)
|
@@ -35,7 +35,13 @@ if defined?(Puma.cli_config)
|
|
35
35
|
|
36
36
|
# Runs initial instrumentation only once on the master process
|
37
37
|
puma_server_starting = Proc.new { TCellAgent.run_instrumentation("Puma Cluster Mode") }
|
38
|
-
|
38
|
+
|
39
|
+
# before_fork was added in Puma v2.13.0
|
40
|
+
if Puma.cli_config.options[:before_fork]
|
41
|
+
Puma.cli_config.options[:before_fork].push(puma_server_starting)
|
42
|
+
else
|
43
|
+
Puma.cli_config.options[:before_fork] = [puma_server_starting]
|
44
|
+
end
|
39
45
|
|
40
46
|
# Each puma worker still needs the agent started but no need to run
|
41
47
|
# initial instrumentation again
|
@@ -58,4 +64,3 @@ if defined?(Puma.cli_config)
|
|
58
64
|
|
59
65
|
end
|
60
66
|
end
|
61
|
-
|
data/lib/tcell_agent/version.rb
CHANGED
@@ -79,7 +79,7 @@ module TCellAgent
|
|
79
79
|
end
|
80
80
|
|
81
81
|
context "with 10 processes updating the cached file" do
|
82
|
-
|
82
|
+
xit "should update the cached file with all updates" do
|
83
83
|
processes = 5.times.map do |process_number|
|
84
84
|
ForkBreak::Process.new do |breakpoints|
|
85
85
|
original_dump = JSON.method(:dump)
|
@@ -0,0 +1,371 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
|
5
|
+
describe Configuration do
|
6
|
+
describe "#load_app_sensor_restrictions" do
|
7
|
+
before(:each) do
|
8
|
+
@config_file = double("config", read: {
|
9
|
+
version: 1,
|
10
|
+
applications: [
|
11
|
+
{
|
12
|
+
allow_unencrypted_appsensor_payloads: true
|
13
|
+
}
|
14
|
+
]
|
15
|
+
}.to_json)
|
16
|
+
end
|
17
|
+
|
18
|
+
context "with no payloads file present" do
|
19
|
+
it "should set blacklist to default params and whitelist to empty" do
|
20
|
+
expect(File).to receive(:file?).with(
|
21
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
22
|
+
).and_return(true)
|
23
|
+
expect(File).to receive(:open).with(
|
24
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
25
|
+
).and_return(@config_file)
|
26
|
+
expect(File).to receive(:file?).with(
|
27
|
+
"config/tcell_agent_payloads.config"
|
28
|
+
).and_return(false)
|
29
|
+
expect(File).to_not receive(:open)
|
30
|
+
configuration = TCellAgent::Configuration.new
|
31
|
+
|
32
|
+
expect(configuration.allow_unencrypted_appsensor_payloads).to eq(true)
|
33
|
+
expect(configuration.blacklisted_params).to eq({
|
34
|
+
"token" => true,
|
35
|
+
"client_secret" => true,
|
36
|
+
"password" => true,
|
37
|
+
"passwd" => true,
|
38
|
+
"refresh_token" => true,
|
39
|
+
"pf.pass" => true,
|
40
|
+
"user.password" => true
|
41
|
+
})
|
42
|
+
expect(configuration.whitelisted_params).to eq({})
|
43
|
+
expect(configuration.whitelist_present).to eq(false)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "with a payloads file present" do
|
48
|
+
context "with a malformed payloads file" do
|
49
|
+
it "should set blacklist to default params and whitelist to empty" do
|
50
|
+
payloads_file = double("payloads", read: "{ whitelist: { test } ")
|
51
|
+
expect(File).to receive(:file?).with(
|
52
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
53
|
+
).and_return(true)
|
54
|
+
expect(File).to receive(:open).with(
|
55
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
56
|
+
).and_return(@config_file)
|
57
|
+
expect(File).to receive(:file?).with("config/tcell_agent_payloads.config").and_return(true)
|
58
|
+
expect(File).to receive(:open).with("config/tcell_agent_payloads.config").and_return(payloads_file)
|
59
|
+
configuration = TCellAgent::Configuration.new
|
60
|
+
|
61
|
+
expect(configuration.allow_unencrypted_appsensor_payloads).to eq(false)
|
62
|
+
expect(configuration.blacklisted_params).to eq({
|
63
|
+
"token" => true,
|
64
|
+
"client_secret" => true,
|
65
|
+
"password" => true,
|
66
|
+
"passwd" => true,
|
67
|
+
"refresh_token" => true,
|
68
|
+
"pf.pass" => true,
|
69
|
+
"user.password" => true
|
70
|
+
})
|
71
|
+
expect(configuration.whitelisted_params).to eq({})
|
72
|
+
expect(configuration.whitelist_present).to eq(false)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "with a payloads file" do
|
77
|
+
context "with empty json" do
|
78
|
+
it "should set blacklist to default params and whitelist to empty" do
|
79
|
+
payloads_file = double("payloads", read: "{}")
|
80
|
+
expect(File).to receive(:file?).with(
|
81
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
82
|
+
).and_return(true)
|
83
|
+
expect(File).to receive(:open).with(
|
84
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
85
|
+
).and_return(@config_file)
|
86
|
+
expect(File).to receive(:file?).with("config/tcell_agent_payloads.config").and_return(true)
|
87
|
+
expect(File).to receive(:open).with("config/tcell_agent_payloads.config").and_return(payloads_file)
|
88
|
+
configuration = TCellAgent::Configuration.new
|
89
|
+
|
90
|
+
expect(configuration.allow_unencrypted_appsensor_payloads).to eq(true)
|
91
|
+
expect(configuration.blacklisted_params).to eq({
|
92
|
+
"token" => true,
|
93
|
+
"client_secret" => true,
|
94
|
+
"password" => true,
|
95
|
+
"passwd" => true,
|
96
|
+
"refresh_token" => true,
|
97
|
+
"pf.pass" => true,
|
98
|
+
"user.password" => true
|
99
|
+
})
|
100
|
+
expect(configuration.whitelisted_params).to eq({})
|
101
|
+
expect(configuration.whitelist_present).to eq(false)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "with blacklisted present" do
|
106
|
+
it "should set blacklist but whitelist is empty" do
|
107
|
+
payloads_file = double("payloads", read:{blacklisted:["passwd"]}.to_json)
|
108
|
+
expect(File).to receive(:file?).with(
|
109
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
110
|
+
).and_return(true)
|
111
|
+
expect(File).to receive(:open).with(
|
112
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
113
|
+
).and_return(@config_file)
|
114
|
+
expect(File).to receive(:file?).with("config/tcell_agent_payloads.config").and_return(true)
|
115
|
+
expect(File).to receive(:open).with("config/tcell_agent_payloads.config").and_return(payloads_file)
|
116
|
+
configuration = TCellAgent::Configuration.new
|
117
|
+
|
118
|
+
expect(configuration.allow_unencrypted_appsensor_payloads).to eq(true)
|
119
|
+
expect(configuration.blacklisted_params).to eq({"passwd" => true})
|
120
|
+
expect(configuration.whitelisted_params).to eq({})
|
121
|
+
expect(configuration.whitelist_present).to eq(false)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "with whitelist present" do
|
126
|
+
it "should set whitelist and blacklist to default params" do
|
127
|
+
payloads_file = double("payloads", read: {whitelisted: ["passwd"]}.to_json)
|
128
|
+
expect(File).to receive(:file?).with(
|
129
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
130
|
+
).and_return(true)
|
131
|
+
expect(File).to receive(:open).with(
|
132
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
133
|
+
).and_return(@config_file)
|
134
|
+
expect(File).to receive(:file?).with("config/tcell_agent_payloads.config").and_return(true)
|
135
|
+
expect(File).to receive(:open).with("config/tcell_agent_payloads.config").and_return(payloads_file)
|
136
|
+
configuration = TCellAgent::Configuration.new
|
137
|
+
|
138
|
+
expect(configuration.allow_unencrypted_appsensor_payloads).to eq(true)
|
139
|
+
expect(configuration.blacklisted_params).to eq({
|
140
|
+
"token" => true,
|
141
|
+
"client_secret" => true,
|
142
|
+
"password" => true,
|
143
|
+
"passwd" => true,
|
144
|
+
"refresh_token" => true,
|
145
|
+
"pf.pass" => true,
|
146
|
+
"user.password" => true
|
147
|
+
})
|
148
|
+
expect(configuration.whitelisted_params).to eq({"passwd" => true})
|
149
|
+
expect(configuration.whitelist_present).to eq(true)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "with blacklist and whitelist present" do
|
154
|
+
it "should set whitelist and blacklist" do
|
155
|
+
payloads_file = double("payloads", read: {blacklisted: ["ssn"], whitelisted: ["passwd"]}.to_json)
|
156
|
+
expect(File).to receive(:file?).with(
|
157
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
158
|
+
).and_return(true)
|
159
|
+
expect(File).to receive(:open).with(
|
160
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
161
|
+
).and_return(@config_file)
|
162
|
+
expect(File).to receive(:file?).with("config/tcell_agent_payloads.config").and_return(true)
|
163
|
+
expect(File).to receive(:open).with("config/tcell_agent_payloads.config").and_return(payloads_file)
|
164
|
+
configuration = TCellAgent::Configuration.new
|
165
|
+
|
166
|
+
expect(configuration.allow_unencrypted_appsensor_payloads).to eq(true)
|
167
|
+
expect(configuration.blacklisted_params).to eq({"ssn" => true})
|
168
|
+
expect(configuration.whitelisted_params).to eq({"passwd" => true})
|
169
|
+
expect(configuration.whitelist_present).to eq(true)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "#agent_home_dir" do
|
178
|
+
context "no TCELL_AGENT_HOME defined" do
|
179
|
+
it "should set cache file, config, and log file to defaults" do
|
180
|
+
configuration = Configuration.new
|
181
|
+
|
182
|
+
expect(configuration.cache_filename).to eq(
|
183
|
+
File.join(Dir.getwd, "tcell/cache/tcell_agent.cache")
|
184
|
+
)
|
185
|
+
expect(configuration.log_filename).to eq(
|
186
|
+
File.join(Dir.getwd, "tcell/logs/tcell_agent.log")
|
187
|
+
)
|
188
|
+
expect(configuration.config_filename).to eq(
|
189
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
190
|
+
)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context "TCELL_AGENT_HOME defined" do
|
195
|
+
it "should set config filename to default, cache file and log file are updated" do
|
196
|
+
old_tcell_agent_home = ENV["TCELL_AGENT_HOME"]
|
197
|
+
|
198
|
+
ENV["TCELL_AGENT_HOME"] = "spec_tcell_home"
|
199
|
+
|
200
|
+
expect(FileUtils).to receive(:mkdir_p).with("spec_tcell_home/cache")
|
201
|
+
expect(FileUtils).to receive(:mkdir_p).with("spec_tcell_home/logs")
|
202
|
+
|
203
|
+
configuration = Configuration.new
|
204
|
+
|
205
|
+
expect(configuration.cache_filename).to eq(
|
206
|
+
"spec_tcell_home/cache/tcell_agent.cache"
|
207
|
+
)
|
208
|
+
expect(configuration.log_filename).to eq(
|
209
|
+
"spec_tcell_home/logs/tcell_agent.log"
|
210
|
+
)
|
211
|
+
expect(configuration.config_filename).to eq(
|
212
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
213
|
+
)
|
214
|
+
|
215
|
+
ENV["TCELL_AGENT_HOME"] = old_tcell_agent_home
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context "TCELL_AGENT_HOME and TCELL_AGENT_LOG_DIR defined" do
|
220
|
+
it "should set config filename to default, cache file and log file are updated" do
|
221
|
+
old_tcell_agent_home = ENV["TCELL_AGENT_HOME"]
|
222
|
+
old_tcell_agent_log_dir = ENV["TCELL_AGENT_LOG_DIR"]
|
223
|
+
|
224
|
+
ENV["TCELL_AGENT_HOME"] = "spec_tcell_home"
|
225
|
+
ENV["TCELL_AGENT_LOG_DIR"] = "spec_tcell_log_dir"
|
226
|
+
|
227
|
+
expect(FileUtils).to receive(:mkdir_p).with("spec_tcell_home/cache")
|
228
|
+
expect(FileUtils).to receive(:mkdir_p).with("spec_tcell_log_dir")
|
229
|
+
|
230
|
+
configuration = Configuration.new
|
231
|
+
|
232
|
+
expect(configuration.cache_filename).to eq(
|
233
|
+
"spec_tcell_home/cache/tcell_agent.cache"
|
234
|
+
)
|
235
|
+
expect(configuration.log_filename).to eq(
|
236
|
+
"spec_tcell_log_dir/tcell_agent.log"
|
237
|
+
)
|
238
|
+
expect(configuration.config_filename).to eq(
|
239
|
+
File.join(Dir.getwd, "config/tcell_agent.config")
|
240
|
+
)
|
241
|
+
|
242
|
+
ENV["TCELL_AGENT_HOME"] = old_tcell_agent_home
|
243
|
+
ENV["TCELL_AGENT_LOG_DIR"] = old_tcell_agent_log_dir
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
context "TCELL_AGENT_HOME, TCELL_AGENT_LOG_DIR, and TCELL_AGENT_CONFIG defined " do
|
248
|
+
it "should update config filename, cache file, and log file" do
|
249
|
+
old_tcell_agent_home = ENV["TCELL_AGENT_HOME"]
|
250
|
+
old_tcell_agent_log_dir = ENV["TCELL_AGENT_LOG_DIR"]
|
251
|
+
old_config_filename = ENV["TCELL_AGENT_CONFIG"]
|
252
|
+
|
253
|
+
ENV["TCELL_AGENT_HOME"] = "spec_tcell_home"
|
254
|
+
ENV["TCELL_AGENT_LOG_DIR"] = "spec_tcell_log_dir"
|
255
|
+
ENV["TCELL_AGENT_CONFIG"] = "spec_config/tcell_agent.config"
|
256
|
+
|
257
|
+
expect(FileUtils).to receive(:mkdir_p).with("spec_tcell_log_dir")
|
258
|
+
expect(FileUtils).to receive(:mkdir_p).with("spec_tcell_home/cache")
|
259
|
+
|
260
|
+
configuration = Configuration.new
|
261
|
+
|
262
|
+
expect(configuration.cache_filename).to eq(
|
263
|
+
"spec_tcell_home/cache/tcell_agent.cache"
|
264
|
+
)
|
265
|
+
expect(configuration.log_filename).to eq(
|
266
|
+
"spec_tcell_log_dir/tcell_agent.log"
|
267
|
+
)
|
268
|
+
expect(configuration.config_filename).to eq(
|
269
|
+
"spec_config/tcell_agent.config"
|
270
|
+
)
|
271
|
+
|
272
|
+
ENV["TCELL_AGENT_HOME"] = old_tcell_agent_home
|
273
|
+
ENV["TCELL_AGENT_LOG_DIR"] = old_tcell_agent_log_dir
|
274
|
+
ENV["TCELL_AGENT_CONFIG"] = old_config_filename
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe "#data_exposure" do
|
280
|
+
context "no data_exposure defined" do
|
281
|
+
it "should set max_data_ex_db_records_per_request to default" do
|
282
|
+
no_data_ex = double(
|
283
|
+
"no_data_ex",
|
284
|
+
read: {
|
285
|
+
version: 1,
|
286
|
+
applications: [
|
287
|
+
app_id: "app_id",
|
288
|
+
name: "test",
|
289
|
+
api_key: "api_key"
|
290
|
+
]
|
291
|
+
}.to_json
|
292
|
+
)
|
293
|
+
expect(File).to receive(:file?).with(
|
294
|
+
File.join(Dir.getwd, "no_data_ex.config")
|
295
|
+
).and_return(true)
|
296
|
+
expect(File).to receive(:open).with(
|
297
|
+
File.join(Dir.getwd, "no_data_ex.config")
|
298
|
+
).and_return(no_data_ex)
|
299
|
+
expect(File).to receive(:file?).with(
|
300
|
+
"config/tcell_agent_payloads.config"
|
301
|
+
).and_return(false)
|
302
|
+
configuration = Configuration.new("no_data_ex.config")
|
303
|
+
|
304
|
+
expect(configuration.max_data_ex_db_records_per_request).to eq(1000)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
context "data_exposure is empty" do
|
309
|
+
it "should set max_data_ex_db_records_per_request to default" do
|
310
|
+
no_data_ex = double(
|
311
|
+
"no_data_ex",
|
312
|
+
read: {
|
313
|
+
version: 1,
|
314
|
+
applications: [
|
315
|
+
app_id: "app_id",
|
316
|
+
name: "test",
|
317
|
+
api_key: "api_key",
|
318
|
+
data_exposure: {}
|
319
|
+
]
|
320
|
+
}.to_json
|
321
|
+
)
|
322
|
+
expect(File).to receive(:file?).with(
|
323
|
+
File.join(Dir.getwd, "no_data_ex.config")
|
324
|
+
).and_return(true)
|
325
|
+
expect(File).to receive(:open).with(
|
326
|
+
File.join(Dir.getwd, "no_data_ex.config")
|
327
|
+
).and_return(no_data_ex)
|
328
|
+
expect(File).to receive(:file?).with(
|
329
|
+
"config/tcell_agent_payloads.config"
|
330
|
+
).and_return(false)
|
331
|
+
configuration = Configuration.new("no_data_ex.config")
|
332
|
+
|
333
|
+
expect(configuration.max_data_ex_db_records_per_request).to eq(1000)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
context "data_exposure contains an override" do
|
338
|
+
it "should set max_data_ex_db_records_per_request to override" do
|
339
|
+
no_data_ex = double(
|
340
|
+
"no_data_ex",
|
341
|
+
read: {
|
342
|
+
version: 1,
|
343
|
+
applications: [
|
344
|
+
app_id: "app_id",
|
345
|
+
name: "test",
|
346
|
+
api_key: "api_key",
|
347
|
+
data_exposure: {
|
348
|
+
max_data_ex_db_records_per_request: 5000
|
349
|
+
}
|
350
|
+
]
|
351
|
+
}.to_json
|
352
|
+
)
|
353
|
+
expect(File).to receive(:file?).with(
|
354
|
+
File.join(Dir.getwd, "no_data_ex.config")
|
355
|
+
).and_return(true)
|
356
|
+
expect(File).to receive(:open).with(
|
357
|
+
File.join(Dir.getwd, "no_data_ex.config")
|
358
|
+
).and_return(no_data_ex)
|
359
|
+
expect(File).to receive(:file?).with(
|
360
|
+
"config/tcell_agent_payloads.config"
|
361
|
+
).and_return(false)
|
362
|
+
configuration = Configuration.new("no_data_ex.config")
|
363
|
+
|
364
|
+
expect(configuration.max_data_ex_db_records_per_request).to eq(5000)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
@@ -64,24 +64,24 @@ module TCellAgent
|
|
64
64
|
end
|
65
65
|
it "alerts on get xss payload" do
|
66
66
|
response = request.get("/foo?xyz=%3Cscript%3Ealert(1)%3C%2Fscript%3E", 'REMOTE_ADDR' => '1.3.3.4,3.4.5.6')
|
67
|
-
expected_as = {"event_type"=>"as", "dp"=>"xss", "param"=>"xyz", "remote_addr"=>"1.3.3.4", "m"=>"GET", "loc"=>"/foo?xyz=", "tid"=>"a-b-c-d-e-f"}
|
67
|
+
expected_as = {"event_type"=>"as", "dp"=>"xss", "param"=>"xyz", "remote_addr"=>"1.3.3.4", "m"=>"GET", "loc"=>"http://example.org/foo?xyz=", "tid"=>"a-b-c-d-e-f"}
|
68
68
|
expect(TCellAgent.event_queue).to include(expected_as)
|
69
69
|
end
|
70
70
|
it "alerts on post xss payload" do
|
71
71
|
response = request.post("/foo", :input => "x=<script>alert(1)</script>", 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6')
|
72
|
-
expected_as = {"event_type"=>"as", "dp"=>"xss", "param"=>"x", "remote_addr"=>"1.2.3.4", "m"=>"POST", "loc"=>"/foo", "tid"=>"a-b-c-d-e-f"}
|
72
|
+
expected_as = {"event_type"=>"as", "dp"=>"xss", "param"=>"x", "remote_addr"=>"1.2.3.4", "m"=>"POST", "loc"=>"http://example.org/foo", "tid"=>"a-b-c-d-e-f"}
|
73
73
|
expect(TCellAgent.event_queue).to include(expected_as)
|
74
74
|
end #/it
|
75
75
|
it "alerts on get xss payload with route_id" do
|
76
76
|
response = request2.get("/foo?xyz=%3Cscript%3Ealert(1)%3C%2Fscript%3E")
|
77
|
-
expected_as = {"event_type"=>"as", "dp"=>"xss", "param"=>"xyz", "remote_addr"=>nil, "rou"=>"myrouteid", "m"=>"GET", "loc"=>"/foo?xyz=", "tid"=>"a-b-c-d-e-f"}
|
77
|
+
expected_as = {"event_type"=>"as", "dp"=>"xss", "param"=>"xyz", "remote_addr"=>nil, "rou"=>"myrouteid", "m"=>"GET", "loc"=>"http://example.org/foo?xyz=", "tid"=>"a-b-c-d-e-f"}
|
78
78
|
expect(TCellAgent.event_queue).to include(expected_as)
|
79
79
|
end
|
80
80
|
it "checks that payload is sent in xss with route_id" do
|
81
81
|
old_uap = TCellAgent.configuration.allow_unencrypted_appsensor_payloads
|
82
82
|
TCellAgent.configuration.allow_unencrypted_appsensor_payloads = true
|
83
83
|
response = request2.get("/foo?xyz=%3Cscript%3Ealert(1)%3C%2Fscript%3E")
|
84
|
-
expected_as = {"event_type"=>"as", "dp"=>"xss", "param"=>"xyz", "remote_addr"=>nil, "rou"=>"myrouteid", "m"=>"GET", "loc"=>"/foo?xyz=", "tid"=>"a-b-c-d-e-f", "payload"=>"<script>alert(1)</script>"}
|
84
|
+
expected_as = {"event_type"=>"as", "dp"=>"xss", "param"=>"xyz", "remote_addr"=>nil, "rou"=>"myrouteid", "m"=>"GET", "loc"=>"http://example.org/foo?xyz=", "tid"=>"a-b-c-d-e-f", "payload"=>"<script>alert(1)</script>"}
|
85
85
|
TCellAgent.configuration.allow_unencrypted_appsensor_payloads = old_uap
|
86
86
|
expect(TCellAgent.event_queue).to include(expected_as)
|
87
87
|
end
|
@@ -104,7 +104,7 @@ module TCellAgent
|
|
104
104
|
it "alerts on get sqli payload" do
|
105
105
|
# ' OR '3'='3
|
106
106
|
response = request.get("/foo?xyz=abds&def=%27%20OR%20%273%27%3D%273", 'REMOTE_ADDR' => '1.3.3.4,3.4.5.6')
|
107
|
-
expected_as = {"event_type"=>"as", "dp"=>"sqli", "param"=>"def", "remote_addr"=>"1.3.3.4", "m"=>"GET", "loc"=>"/foo?xyz=&def=", "tid"=>"a-b-c-d-e-f"}
|
107
|
+
expected_as = {"event_type"=>"as", "dp"=>"sqli", "param"=>"def", "remote_addr"=>"1.3.3.4", "m"=>"GET", "loc"=>"http://example.org/foo?xyz=&def=", "tid"=>"a-b-c-d-e-f"}
|
108
108
|
expect(TCellAgent.event_queue).to include(expected_as)
|
109
109
|
end
|
110
110
|
end #/conext
|
@@ -124,14 +124,14 @@ module TCellAgent
|
|
124
124
|
end
|
125
125
|
it "alerts on most obvious payload" do
|
126
126
|
response = request.get("/foo?xyz=/etc/passwd", 'REMOTE_ADDR' => '1.3.3.4,3.4.5.6')
|
127
|
-
expected_as = {"event_type"=>"as", "dp"=>"fpt", "param"=>"xyz", "remote_addr"=>"1.3.3.4", "m"=>"GET", "loc"=>"/foo?xyz=", "tid"=>"a-b-c-d-e-f"}
|
127
|
+
expected_as = {"event_type"=>"as", "dp"=>"fpt", "param"=>"xyz", "remote_addr"=>"1.3.3.4", "m"=>"GET", "loc"=>"http://example.org/foo?xyz=", "tid"=>"a-b-c-d-e-f"}
|
128
128
|
expect(TCellAgent.event_queue).to include(expected_as)
|
129
129
|
end
|
130
130
|
it "checks that payload is sent" do
|
131
131
|
old_uap = TCellAgent.configuration.allow_unencrypted_appsensor_payloads
|
132
132
|
TCellAgent.configuration.allow_unencrypted_appsensor_payloads = true
|
133
133
|
response = request.get("/foo?xyz=/etc/passwd", 'REMOTE_ADDR' => '1.3.3.4,3.4.5.6')
|
134
|
-
expected_as = {"event_type"=>"as", "dp"=>"fpt", "param"=>"xyz", "remote_addr"=>"1.3.3.4", "m"=>"GET", "loc"=>"/foo?xyz=", "tid"=>"a-b-c-d-e-f", "payload"=>"/etc/passwd"}
|
134
|
+
expected_as = {"event_type"=>"as", "dp"=>"fpt", "param"=>"xyz", "remote_addr"=>"1.3.3.4", "m"=>"GET", "loc"=>"http://example.org/foo?xyz=", "tid"=>"a-b-c-d-e-f", "payload"=>"/etc/passwd"}
|
135
135
|
TCellAgent.configuration.allow_unencrypted_appsensor_payloads = old_uap
|
136
136
|
expect(TCellAgent.event_queue).to include(expected_as)
|
137
137
|
end
|
@@ -0,0 +1,289 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module SensorEvents
|
5
|
+
|
6
|
+
describe TCellAppSensorEventProcessor do
|
7
|
+
|
8
|
+
describe "#appsensor_event" do
|
9
|
+
before(:each) do
|
10
|
+
@app_sensor_event_process = TCellAppSensorEventProcessor.new
|
11
|
+
end
|
12
|
+
|
13
|
+
context "whitelist not present" do
|
14
|
+
context "a term that is blacklisted" do
|
15
|
+
it "should obfuscate the payload" do
|
16
|
+
event = double("event")
|
17
|
+
configuration = double(
|
18
|
+
"configuration",
|
19
|
+
whitelist_present: false,
|
20
|
+
raise_exceptions: true,
|
21
|
+
blacklisted_params: double("bp", {"passwd" => true, "has_key?" => true})
|
22
|
+
)
|
23
|
+
|
24
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
25
|
+
expect(TCellAgent::SensorEvents::TCellAppSensorEvent).to receive(:new).with(
|
26
|
+
nil,
|
27
|
+
"xss",
|
28
|
+
nil,
|
29
|
+
nil,
|
30
|
+
"PASSWD",
|
31
|
+
nil,
|
32
|
+
nil,
|
33
|
+
nil,
|
34
|
+
nil,
|
35
|
+
nil,
|
36
|
+
"BLACKLISTED"
|
37
|
+
).and_return(event)
|
38
|
+
expect(TCellAgent).to receive(:send_event)
|
39
|
+
|
40
|
+
@app_sensor_event_process.appsensor_event("xss", "PASSWD", nil, "%3Cscript%3Ealert(1)%3C%2Fscript%3E")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "a term that is not blacklisted" do
|
45
|
+
it "should not obfuscate the payload" do
|
46
|
+
event = double("event")
|
47
|
+
configuration = double(
|
48
|
+
"configuration",
|
49
|
+
whitelist_present: false,
|
50
|
+
raise_exceptions: true,
|
51
|
+
blacklisted_params: double("bp", {"has_key?" => false})
|
52
|
+
)
|
53
|
+
|
54
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
55
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
56
|
+
expect(TCellAgent::SensorEvents::TCellAppSensorEvent).to receive(:new).with(
|
57
|
+
nil,
|
58
|
+
"xss",
|
59
|
+
nil,
|
60
|
+
nil,
|
61
|
+
"PASSWD",
|
62
|
+
nil,
|
63
|
+
nil,
|
64
|
+
nil,
|
65
|
+
nil,
|
66
|
+
nil,
|
67
|
+
"%3Cscript%3Ealert(1)%3C%2Fscript%3E"
|
68
|
+
).and_return(event)
|
69
|
+
expect(TCellAgent).to receive(:send_event)
|
70
|
+
|
71
|
+
@app_sensor_event_process.appsensor_event("xss", "PASSWD", nil, "%3Cscript%3Ealert(1)%3C%2Fscript%3E")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "whitelist present" do
|
77
|
+
context "a term is whitelisted" do
|
78
|
+
context "a term that is blacklisted" do
|
79
|
+
it "should obfuscate the payload" do
|
80
|
+
event = double("event")
|
81
|
+
configuration = double(
|
82
|
+
"configuration",
|
83
|
+
whitelist_present: true,
|
84
|
+
raise_exceptions: true,
|
85
|
+
blacklisted_params: double("bp", {"passwd" => true, "has_key?" => true}),
|
86
|
+
whitelisted_params: double("wp", {"passwd" => true, "has_key?" => true})
|
87
|
+
)
|
88
|
+
|
89
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
90
|
+
expect(TCellAgent::SensorEvents::TCellAppSensorEvent).to receive(:new).with(
|
91
|
+
nil,
|
92
|
+
"xss",
|
93
|
+
nil,
|
94
|
+
nil,
|
95
|
+
"PASSWD",
|
96
|
+
nil,
|
97
|
+
nil,
|
98
|
+
nil,
|
99
|
+
nil,
|
100
|
+
nil,
|
101
|
+
"BLACKLISTED"
|
102
|
+
).and_return(event)
|
103
|
+
expect(TCellAgent).to receive(:send_event)
|
104
|
+
|
105
|
+
@app_sensor_event_process.appsensor_event("xss", "PASSWD", nil, "%3Cscript%3Ealert(1)%3C%2Fscript%3E")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "a term that is not blacklisted" do
|
110
|
+
it "should not obfuscate the payload" do
|
111
|
+
event = double("event")
|
112
|
+
configuration = double(
|
113
|
+
"configuration",
|
114
|
+
whitelist_present: true,
|
115
|
+
raise_exceptions: true,
|
116
|
+
blacklisted_params: double("bp", {"has_key?" => false}),
|
117
|
+
whitelisted_params: double("wp", {"passwd" => true, "has_key?" => true})
|
118
|
+
)
|
119
|
+
|
120
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
121
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
122
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
123
|
+
expect(TCellAgent::SensorEvents::TCellAppSensorEvent).to receive(:new).with(
|
124
|
+
nil,
|
125
|
+
"xss",
|
126
|
+
nil,
|
127
|
+
nil,
|
128
|
+
"PASSWD",
|
129
|
+
nil,
|
130
|
+
nil,
|
131
|
+
nil,
|
132
|
+
nil,
|
133
|
+
nil,
|
134
|
+
"%3Cscript%3Ealert(1)%3C%2Fscript%3E"
|
135
|
+
).and_return(event)
|
136
|
+
expect(TCellAgent).to receive(:send_event)
|
137
|
+
|
138
|
+
@app_sensor_event_process.appsensor_event("xss", "PASSWD", nil, "%3Cscript%3Ealert(1)%3C%2Fscript%3E")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "a term is not whitelisted" do
|
144
|
+
context "a term that is blacklisted" do
|
145
|
+
it "should obfuscate the payload" do
|
146
|
+
event = double("event")
|
147
|
+
configuration = double(
|
148
|
+
"configuration",
|
149
|
+
whitelist_present: true,
|
150
|
+
raise_exceptions: true,
|
151
|
+
blacklisted_params: double("bp", {"passwd" => true, "has_key?" => true}),
|
152
|
+
whitelisted_params: double("wp", {"has_key?" => false})
|
153
|
+
)
|
154
|
+
|
155
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
156
|
+
expect(TCellAgent::SensorEvents::TCellAppSensorEvent).to receive(:new).with(
|
157
|
+
nil,
|
158
|
+
"xss",
|
159
|
+
nil,
|
160
|
+
nil,
|
161
|
+
"PASSWD",
|
162
|
+
nil,
|
163
|
+
nil,
|
164
|
+
nil,
|
165
|
+
nil,
|
166
|
+
nil,
|
167
|
+
"BLACKLISTED"
|
168
|
+
).and_return(event)
|
169
|
+
expect(TCellAgent).to receive(:send_event)
|
170
|
+
|
171
|
+
@app_sensor_event_process.appsensor_event("xss", "PASSWD", nil, "%3Cscript%3Ealert(1)%3C%2Fscript%3E")
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context "a term that is not blacklisted" do
|
176
|
+
it "should obfuscate the payload" do
|
177
|
+
event = double("event")
|
178
|
+
configuration = double(
|
179
|
+
"configuration",
|
180
|
+
whitelist_present: true,
|
181
|
+
raise_exceptions: true,
|
182
|
+
blacklisted_params: double("bp", {"has_key?" => false}),
|
183
|
+
whitelisted_params: double("wp", {"has_key?" => false})
|
184
|
+
)
|
185
|
+
|
186
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
187
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
188
|
+
expect(TCellAgent).to receive(:configuration).and_return(configuration)
|
189
|
+
expect(TCellAgent::SensorEvents::TCellAppSensorEvent).to receive(:new).with(
|
190
|
+
nil,
|
191
|
+
"xss",
|
192
|
+
nil,
|
193
|
+
nil,
|
194
|
+
"PASSWD",
|
195
|
+
nil,
|
196
|
+
nil,
|
197
|
+
nil,
|
198
|
+
nil,
|
199
|
+
nil,
|
200
|
+
"NOT_WHITELISTED"
|
201
|
+
).and_return(event)
|
202
|
+
expect(TCellAgent).to receive(:send_event)
|
203
|
+
|
204
|
+
@app_sensor_event_process.appsensor_event("xss", "PASSWD", nil, "%3Cscript%3Ealert(1)%3C%2Fscript%3E")
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe "#for_params" do
|
212
|
+
context "with body_params" do
|
213
|
+
it "should iterate over body params" do
|
214
|
+
app_sensor_event_process = TCellAppSensorEventProcessor.new
|
215
|
+
app_sensor_event_process.request_content_length = 67
|
216
|
+
app_sensor_event_process.request_content_type = "application/json"
|
217
|
+
app_sensor_event_process.request_body = {username:"tester",password:"pass"}.to_json
|
218
|
+
|
219
|
+
expect(app_sensor_event_process.body_params).to eq({"username"=>"tester","password"=>"pass"})
|
220
|
+
|
221
|
+
iterated_over = {}
|
222
|
+
|
223
|
+
app_sensor_event_process.for_params do |method, param_name, param_value|
|
224
|
+
iterated_over[param_name] = param_value
|
225
|
+
end
|
226
|
+
|
227
|
+
expect(iterated_over).to eq({"username"=>"tester", "password"=>"pass"})
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe "#body_params" do
|
233
|
+
context "with text/html content type" do
|
234
|
+
it "should set the body params to empty" do
|
235
|
+
app_sensor_event_process = TCellAppSensorEventProcessor.new
|
236
|
+
app_sensor_event_process.request_content_length = 67
|
237
|
+
app_sensor_event_process.request_content_type = "text/html"
|
238
|
+
app_sensor_event_process.request_body = {username:"tester",password:"pass"}.to_json
|
239
|
+
|
240
|
+
expect(app_sensor_event_process.body_params).to eq({})
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
context "with application/json content type" do
|
245
|
+
before(:each) do
|
246
|
+
@app_sensor_event_process = TCellAppSensorEventProcessor.new
|
247
|
+
@app_sensor_event_process.request_content_length = 67
|
248
|
+
@app_sensor_event_process.request_content_type = "application/json"
|
249
|
+
end
|
250
|
+
|
251
|
+
context "with empty request body" do
|
252
|
+
it "should set the body params to empty" do
|
253
|
+
@app_sensor_event_process.request_body = nil
|
254
|
+
|
255
|
+
expect(@app_sensor_event_process.body_params).to eq({})
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context "with bad json in the body" do
|
260
|
+
it "should set the body params to empty" do
|
261
|
+
@app_sensor_event_process.request_body = '{"username":"tester""password":"pass"}'
|
262
|
+
|
263
|
+
expect(@app_sensor_event_process.body_params).to eq({})
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
context "with valid json in the body" do
|
268
|
+
it "should set the body params" do
|
269
|
+
@app_sensor_event_process.request_body = {username:"tester",password:"pass"}.to_json
|
270
|
+
|
271
|
+
expect(@app_sensor_event_process.body_params).to eq({"username"=>"tester","password"=>"pass"})
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
context "with a json body that's too big" do
|
276
|
+
it "should set the body params to empty" do
|
277
|
+
@app_sensor_event_process.request_content_length = 2000000
|
278
|
+
@app_sensor_event_process.request_body = '{"username":"tester""password":"pass"}'
|
279
|
+
|
280
|
+
expect(@app_sensor_event_process.body_params).to eq({})
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tcell_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Garrett
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -234,6 +234,7 @@ files:
|
|
234
234
|
- spec/lib/tcell_agent/agent/static_agent_spec.rb
|
235
235
|
- spec/lib/tcell_agent/api/api_spec.rb
|
236
236
|
- spec/lib/tcell_agent/appsensor_spec.rb
|
237
|
+
- spec/lib/tcell_agent/configuration_spec.rb
|
237
238
|
- spec/lib/tcell_agent/instrumentation_spec.rb
|
238
239
|
- spec/lib/tcell_agent/policies/appsensor_policy_spec.rb
|
239
240
|
- spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb
|
@@ -252,6 +253,7 @@ files:
|
|
252
253
|
- spec/lib/tcell_agent/rails_spec.rb
|
253
254
|
- spec/lib/tcell_agent/sensor_events/dlp_spec.rb
|
254
255
|
- spec/lib/tcell_agent/sensor_events/sessions_metric_spec.rb
|
256
|
+
- spec/lib/tcell_agent/sensor_events/tcell_app_sensor_event_processor_spec.rb
|
255
257
|
- spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb
|
256
258
|
- spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb
|
257
259
|
- spec/lib/tcell_agent/utils/bounded_queue_spec.rb
|
@@ -338,6 +340,7 @@ test_files:
|
|
338
340
|
- spec/lib/tcell_agent/agent/static_agent_spec.rb
|
339
341
|
- spec/lib/tcell_agent/api/api_spec.rb
|
340
342
|
- spec/lib/tcell_agent/appsensor_spec.rb
|
343
|
+
- spec/lib/tcell_agent/configuration_spec.rb
|
341
344
|
- spec/lib/tcell_agent/instrumentation_spec.rb
|
342
345
|
- spec/lib/tcell_agent/policies/appsensor_policy_spec.rb
|
343
346
|
- spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb
|
@@ -356,6 +359,7 @@ test_files:
|
|
356
359
|
- spec/lib/tcell_agent/rails_spec.rb
|
357
360
|
- spec/lib/tcell_agent/sensor_events/dlp_spec.rb
|
358
361
|
- spec/lib/tcell_agent/sensor_events/sessions_metric_spec.rb
|
362
|
+
- spec/lib/tcell_agent/sensor_events/tcell_app_sensor_event_processor_spec.rb
|
359
363
|
- spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb
|
360
364
|
- spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb
|
361
365
|
- spec/lib/tcell_agent/utils/bounded_queue_spec.rb
|