tcell_agent 0.2.18 → 0.2.19

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +11 -0
  3. data/lib/tcell_agent/configuration.rb +8 -1
  4. data/lib/tcell_agent/instrumentation.rb +14 -10
  5. data/lib/tcell_agent/logger.rb +23 -23
  6. data/lib/tcell_agent/policies/appsensor/database_sensor.rb +61 -0
  7. data/lib/tcell_agent/policies/appsensor/injection_sensor.rb +10 -2
  8. data/lib/tcell_agent/policies/appsensor/misc_sensor.rb +66 -0
  9. data/lib/tcell_agent/policies/appsensor/response_codes_sensor.rb +11 -3
  10. data/lib/tcell_agent/policies/appsensor/size_sensor.rb +6 -5
  11. data/lib/tcell_agent/policies/appsensor/user_agent_sensor.rb +47 -0
  12. data/lib/tcell_agent/policies/appsensor_policy.rb +68 -5
  13. data/lib/tcell_agent/policies/patches_policy.rb +2 -2
  14. data/lib/tcell_agent/rails.rb +3 -0
  15. data/lib/tcell_agent/rails/auth/authlogic.rb +2 -2
  16. data/lib/tcell_agent/rails/auth/devise.rb +4 -4
  17. data/lib/tcell_agent/rails/better_ip.rb +36 -0
  18. data/lib/tcell_agent/rails/csrf_exception.rb +30 -0
  19. data/lib/tcell_agent/rails/dlp.rb +38 -76
  20. data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +5 -5
  21. data/lib/tcell_agent/rails/middleware/context_middleware.rb +6 -4
  22. data/lib/tcell_agent/rails/middleware/global_middleware.rb +7 -7
  23. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +15 -15
  24. data/lib/tcell_agent/rails/path_parameters_setter.rb +43 -0
  25. data/lib/tcell_agent/rails/routes.rb +4 -4
  26. data/lib/tcell_agent/sensor_events/appsensor_meta_event.rb +11 -6
  27. data/lib/tcell_agent/version.rb +1 -1
  28. data/spec/lib/tcell_agent/policies/appsensor/database_sensor_spec.rb +165 -0
  29. data/spec/lib/tcell_agent/policies/appsensor/misc_sensor_spec.rb +432 -0
  30. data/spec/lib/tcell_agent/policies/appsensor/request_size_sensor_spec.rb +4 -4
  31. data/spec/lib/tcell_agent/policies/appsensor/response_codes_sensor_spec.rb +99 -24
  32. data/spec/lib/tcell_agent/policies/appsensor/response_size_sensor_spec.rb +4 -4
  33. data/spec/lib/tcell_agent/policies/appsensor/user_agent_sensor_spec.rb +156 -0
  34. data/spec/lib/tcell_agent/policies/appsensor/xss_sensor_spec.rb +175 -0
  35. data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +79 -0
  36. data/spec/lib/tcell_agent/rails/better_ip_spec.rb +76 -0
  37. metadata +16 -2
@@ -40,6 +40,16 @@ module TCellAgent
40
40
  expect(sensor.series_500_enabled).to eq(true)
41
41
  end
42
42
  end
43
+
44
+ context "setting excluded_route_ids on sensor" do
45
+ it "should have excluded_route_ids" do
46
+ sensor = ResponseCodesSensor.new({"exclude_routes" => ["excluded_route_id"]})
47
+ expect(sensor.enabled).to eq(false)
48
+ expect(sensor.series_400_enabled).to eq(false)
49
+ expect(sensor.series_500_enabled).to eq(false)
50
+ expect(sensor.excluded_route_ids).to eq({"excluded_route_id" => true})
51
+ end
52
+ end
43
53
  end
44
54
 
45
55
  context "#check" do
@@ -62,19 +72,50 @@ module TCellAgent
62
72
 
63
73
  context "with enabled sensor" do
64
74
  context "with 200 response code" do
75
+ before(:each) do
76
+ @sensor = ResponseCodesSensor.new({"enabled" => true})
77
+
78
+ @meta = TCellAgent::SensorEvents::AppSensorMetaEvent.new
79
+ @meta.remote_address = "remote_address"
80
+ @meta.method = "get"
81
+ @meta.location = "location"
82
+ @meta.route_id = "route_id"
83
+ @meta.session_id = "session_id"
84
+ @meta.user_id = "user_id"
85
+ @meta.transaction_id = "transaction_id"
86
+ end
87
+
65
88
  it "should not send an event" do
66
- sensor = ResponseCodesSensor.new({"enabled" => true})
67
- meta = TCellAgent::SensorEvents::AppSensorMetaEvent.new
68
- meta.remote_address = "remote_address"
69
- meta.method = "get"
70
- meta.location = "location"
71
- meta.route_id = "route_id"
72
- meta.session_id = "session_id"
73
- meta.user_id = "user_id"
74
- meta.transaction_id = "transaction_id"
89
+ expect(@sensor).to_not receive(:send_event)
90
+ @sensor.check(@meta, 200)
91
+ end
75
92
 
76
- expect(sensor).to_not receive(:send_event)
77
- sensor.check(meta, 200)
93
+ context "no excluded routes" do
94
+ it "should not send an event" do
95
+ @sensor.excluded_route_ids = {}
96
+
97
+ expect(@sensor).to_not receive(:send_event)
98
+ @sensor.check(@meta, 200)
99
+ end
100
+ end
101
+
102
+ context "has excluded routes" do
103
+ context "route id matches" do
104
+ it "should not send an event" do
105
+ @sensor.excluded_route_ids = {"route_id" => true}
106
+
107
+ expect(@sensor).to_not receive(:send_event)
108
+ @sensor.check(@meta, 200)
109
+ end
110
+ end
111
+ context "route id does not match" do
112
+ it "should not send an event" do
113
+ @sensor.excluded_route_ids = {"unmatching_route_id" => true}
114
+
115
+ expect(@sensor).to_not receive(:send_event)
116
+ @sensor.check(@meta, 200)
117
+ end
118
+ end
78
119
  end
79
120
  end
80
121
 
@@ -119,24 +160,58 @@ module TCellAgent
119
160
 
120
161
  context "with enabled series_400_enabled" do
121
162
  context "with 400 response code" do
122
- it "should send an event" do
123
- sensor = ResponseCodesSensor.new({
163
+ before(:each) do
164
+ @sensor = ResponseCodesSensor.new({
124
165
  "enabled" => true,
125
166
  "series_400_enabled" => true
126
167
  })
127
- meta = TCellAgent::SensorEvents::AppSensorMetaEvent.new
128
- meta.remote_address = "remote_address"
129
- meta.method = "get"
130
- meta.location = "location"
131
- meta.route_id = "route_id"
132
- meta.session_id = "session_id"
133
- meta.user_id = "user_id"
134
- meta.transaction_id = "transaction_id"
168
+ @meta = TCellAgent::SensorEvents::AppSensorMetaEvent.new
169
+ @meta.remote_address = "remote_address"
170
+ @meta.method = "get"
171
+ @meta.location = "location"
172
+ @meta.route_id = "route_id"
173
+ @meta.session_id = "session_id"
174
+ @meta.user_id = "user_id"
175
+ @meta.transaction_id = "transaction_id"
176
+ end
135
177
 
136
- expect(sensor).to receive(:send_event).with(
137
- meta, ResponseCodesSensor::RESPONSE_CODE_DP_DICT[4], "400", nil
178
+ it "should send an event" do
179
+ expect(@sensor).to receive(:send_event).with(
180
+ @meta, ResponseCodesSensor::RESPONSE_CODE_DP_DICT[4], "400", nil
138
181
  )
139
- sensor.check(meta, 400)
182
+ @sensor.check(@meta, 400)
183
+ end
184
+
185
+ context "no excluded routes" do
186
+ it "should send an event" do
187
+ @sensor.excluded_route_ids = {}
188
+
189
+ expect(@sensor).to receive(:send_event).with(
190
+ @meta, ResponseCodesSensor::RESPONSE_CODE_DP_DICT[4], "400", nil
191
+ )
192
+ @sensor.check(@meta, 400)
193
+ end
194
+ end
195
+
196
+ context "has excluded routes" do
197
+ context "route id matches" do
198
+ it "should not send an event" do
199
+ @sensor.excluded_route_ids = {"route_id" => true}
200
+
201
+ expect(@sensor).to_not receive(:send_event)
202
+ @sensor.check(@meta, 400)
203
+ end
204
+ end
205
+ context "route id does not match" do
206
+ it "should send an event" do
207
+ @sensor.excluded_route_ids = {"unmatching_route_id" => true}
208
+
209
+ expect(@sensor).to receive(:send_event).with(
210
+ @meta, ResponseCodesSensor::RESPONSE_CODE_DP_DICT[4], "400", nil
211
+ )
212
+ @sensor.check(@meta, 400)
213
+ end
214
+ end
140
215
  end
141
216
  end
142
217
  end
@@ -10,7 +10,7 @@ module TCellAgent
10
10
  sensor = ResponseSizeSensor.new
11
11
  expect(sensor.enabled).to eq(false)
12
12
  expect(sensor.limit).to eq(2097152)
13
- expect(sensor.exclude_routes).to eq({})
13
+ expect(sensor.excluded_route_ids).to eq({})
14
14
  expect(sensor.dp_code).to eq(ResponseSizeSensor::DP_UNUSUAL_RESPONSE_SIZE)
15
15
  end
16
16
  end
@@ -20,7 +20,7 @@ module TCellAgent
20
20
  sensor = ResponseSizeSensor.new({"enabled" => true})
21
21
  expect(sensor.enabled).to eq(true)
22
22
  expect(sensor.limit).to eq(2097152)
23
- expect(sensor.exclude_routes).to eq({})
23
+ expect(sensor.excluded_route_ids).to eq({})
24
24
  expect(sensor.dp_code).to eq(ResponseSizeSensor::DP_UNUSUAL_RESPONSE_SIZE)
25
25
  end
26
26
  end
@@ -30,7 +30,7 @@ module TCellAgent
30
30
  sensor = ResponseSizeSensor.new({"limit" => 1})
31
31
  expect(sensor.enabled).to eq(false)
32
32
  expect(sensor.limit).to eq(1)
33
- expect(sensor.exclude_routes).to eq({})
33
+ expect(sensor.excluded_route_ids).to eq({})
34
34
  expect(sensor.dp_code).to eq(ResponseSizeSensor::DP_UNUSUAL_RESPONSE_SIZE)
35
35
  end
36
36
  end
@@ -40,7 +40,7 @@ module TCellAgent
40
40
  sensor = ResponseSizeSensor.new({"exclude_routes" => ["1", "10", "20"]})
41
41
  expect(sensor.enabled).to eq(false)
42
42
  expect(sensor.limit).to eq(2097152)
43
- expect(sensor.exclude_routes).to eq({"1"=>true, "10"=>true, "20"=>true})
43
+ expect(sensor.excluded_route_ids).to eq({"1"=>true, "10"=>true, "20"=>true})
44
44
  expect(sensor.dp_code).to eq(ResponseSizeSensor::DP_UNUSUAL_RESPONSE_SIZE)
45
45
  end
46
46
  end
@@ -0,0 +1,156 @@
1
+ require 'spec_helper'
2
+
3
+ module TCellAgent
4
+ module Policies
5
+
6
+ describe UserAgentSensor do
7
+ context "#initialize" do
8
+ context "default sensor" do
9
+ it "should have properties set to defaults" do
10
+ sensor = UserAgentSensor.new
11
+ expect(sensor.enabled).to eq(false)
12
+ expect(sensor.empty_enabled).to eq(false)
13
+ expect(UserAgentSensor::DP_CODE).to eq("uaempty")
14
+ end
15
+ end
16
+
17
+ context "setting enabled on sensor" do
18
+ it "should have properties set to defaults" do
19
+ sensor = UserAgentSensor.new({"enabled" => true, "empty_enabled" => false})
20
+ expect(sensor.enabled).to eq(true)
21
+ expect(sensor.empty_enabled).to eq(false)
22
+ end
23
+ end
24
+
25
+ context "setting empty_enabled on sensor" do
26
+ it "should have properties set to defaults" do
27
+ sensor = UserAgentSensor.new({"enabled" => false, "empty_enabled" => true})
28
+ expect(sensor.enabled).to eq(false)
29
+ expect(sensor.empty_enabled).to eq(true)
30
+ end
31
+ end
32
+
33
+ context "setting exclude_routes on sensor" do
34
+ it "should exclude_routes set" do
35
+ sensor = UserAgentSensor.new({
36
+ "enabled" => false,
37
+ "empty_enabled" => true,
38
+ "exclude_routes" => ["route_id"]
39
+ })
40
+ expect(sensor.enabled).to eq(false)
41
+ expect(sensor.empty_enabled).to eq(true)
42
+ expect(sensor.excluded_route_ids).to eq({"route_id" => true})
43
+ end
44
+ end
45
+ end
46
+
47
+ context "#check" do
48
+ before(:each) do
49
+ @meta = TCellAgent::SensorEvents::AppSensorMetaEvent.new
50
+ @meta.remote_address = "remote_address"
51
+ @meta.method = "get"
52
+ @meta.location = "location"
53
+ @meta.route_id = "route_id"
54
+ @meta.session_id = "session_id"
55
+ @meta.user_id = "user_id"
56
+ @meta.transaction_id = "transaction_id"
57
+ end
58
+
59
+ context "with disabled sensor" do
60
+ context "with empty user agent" do
61
+ it "should not send event" do
62
+ sensor = UserAgentSensor.new({"enabled" => false, "empty_enabled" => false})
63
+ @meta.user_agent = nil
64
+
65
+ expect(sensor).to_not receive(:send_event)
66
+ sensor.check(@meta)
67
+ end
68
+ end
69
+
70
+ context "with user agent present" do
71
+ it "should not send event" do
72
+ sensor = UserAgentSensor.new({"enabled" => false, "empty_enabled" => false})
73
+ @meta.user_agent = "Mozilla"
74
+
75
+ expect(sensor).to_not receive(:send_event)
76
+ sensor.check(@meta)
77
+ end
78
+ end
79
+ end
80
+
81
+ context "with enabled sensor" do
82
+ before(:each) do
83
+ @sensor = UserAgentSensor.new({"enabled" => true, "empty_enabled" => true})
84
+ end
85
+
86
+ context "with empty user agent" do
87
+ it "should send event" do
88
+ @meta.user_agent = ""
89
+
90
+ expect(@sensor).to receive(:send_event).with(
91
+ @meta, UserAgentSensor::DP_CODE, nil, nil
92
+ )
93
+ @sensor.check(@meta)
94
+ end
95
+
96
+ context "no excluded routes" do
97
+ it "should send an event" do
98
+ @meta.user_agent = ""
99
+ @sensor.excluded_route_ids = {}
100
+
101
+ expect(@sensor).to receive(:send_event).with(
102
+ @meta, UserAgentSensor::DP_CODE, nil, nil
103
+ )
104
+ @sensor.check(@meta)
105
+ end
106
+ end
107
+
108
+ context "has excluded routes" do
109
+ context "route id matches" do
110
+ it "should not send an event" do
111
+ @meta.user_agent = ""
112
+ @sensor.excluded_route_ids = {"route_id" => true}
113
+
114
+ expect(@sensor).to_not receive(:send_event)
115
+ @sensor.check(@meta)
116
+ end
117
+ end
118
+ context "route id does not match" do
119
+ it "should send an event" do
120
+ @meta.user_agent = ""
121
+ @sensor.excluded_route_ids = {"nonmatching" => true}
122
+
123
+ expect(@sensor).to receive(:send_event).with(
124
+ @meta, UserAgentSensor::DP_CODE, nil, nil
125
+ )
126
+ @sensor.check(@meta)
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ context "with blank space user agent" do
133
+ it "should not send event" do
134
+ @meta.user_agent = "\n \t \s"
135
+
136
+ expect(@sensor).to receive(:send_event).with(
137
+ @meta, UserAgentSensor::DP_CODE, nil, nil
138
+ )
139
+ @sensor.check(@meta)
140
+ end
141
+ end
142
+
143
+ context "with user agent present" do
144
+ it "should not send event" do
145
+ @meta.user_agent = "Mozilla"
146
+
147
+ expect(@sensor).to_not receive(:send_event)
148
+ @sensor.check(@meta)
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ end
156
+ end
@@ -144,6 +144,21 @@ module TCellAgent
144
144
  end
145
145
  end
146
146
 
147
+ context "setting excluded_route_ids on sensor" do
148
+ it "should have excluded_route_ids" do
149
+ sensor = XssSensor.new({"exclude_routes" => ["excluded_route_id"]})
150
+ expect(sensor.enabled).to eq(false)
151
+ expect(sensor.libinjection).to eq(false)
152
+ expect(sensor.detection_point).to eq("xss")
153
+ expect(sensor.exclude_headers).to eq(false)
154
+ expect(sensor.exclude_forms).to eq(false)
155
+ expect(sensor.exclude_cookies).to eq(false)
156
+ expect(sensor.exclusions).to eq({})
157
+ expect(sensor.active_pattern_ids).to eq({})
158
+ expect(sensor.v1_compatability_enabled).to eq(false)
159
+ expect(sensor.excluded_route_ids).to eq({"excluded_route_id" => true})
160
+ end
161
+ end
147
162
  end
148
163
 
149
164
  describe "#find_vulnerability" do
@@ -211,6 +226,7 @@ module TCellAgent
211
226
  before(:each) do
212
227
  @sensor = XssSensor.new({"enabled" => true})
213
228
  end
229
+
214
230
  context "param has NO vulnerability" do
215
231
  it "should return false" do
216
232
  sensor = XssSensor.new({"enabled" => false})
@@ -218,6 +234,34 @@ module TCellAgent
218
234
 
219
235
  expect(result).to eq(false)
220
236
  end
237
+
238
+ context "no excluded routes" do
239
+ it "should return false" do
240
+ sensor = XssSensor.new({"enabled" => false, "exclude_routes" => []})
241
+ result = sensor.check(XssSensor::GET_PARAM, @meta, "param_name", "param_value")
242
+
243
+ expect(result).to eq(false)
244
+ end
245
+ end
246
+
247
+ context "has excluded routes" do
248
+ context "route id matches" do
249
+ it "should return false" do
250
+ sensor = XssSensor.new({"enabled" => false, "exclude_routes" => ["route_id"]})
251
+ result = sensor.check(XssSensor::GET_PARAM, @meta, "param_name", "param_value")
252
+
253
+ expect(result).to eq(false)
254
+ end
255
+ end
256
+ context "route id does not match" do
257
+ it "should return false" do
258
+ sensor = XssSensor.new({"enabled" => false, "exclude_routes" => ["unmatching_route_id"]})
259
+ result = sensor.check(XssSensor::GET_PARAM, @meta, "param_name", "param_value")
260
+
261
+ expect(result).to eq(false)
262
+ end
263
+ end
264
+ end
221
265
  end
222
266
 
223
267
  context "param has a vulnerability" do
@@ -235,6 +279,55 @@ module TCellAgent
235
279
 
236
280
  expect(result).to eq(false)
237
281
  end
282
+
283
+ context "no excluded routes" do
284
+ it "should return false" do
285
+ @sensor.exclude_forms = true
286
+ @sensor.exclude_cookies = false
287
+ @sensor.excluded_route_ids = {}
288
+
289
+ expect(TCellAgent).to_not receive(:configuration)
290
+ expect(@sensor).to_not receive(:find_vulnerability)
291
+ expect(@sensor).to_not receive(:send_event)
292
+
293
+ result = @sensor.check(XssSensor::GET_PARAM, @meta, "param_name", "param_value")
294
+
295
+ expect(result).to eq(false)
296
+ end
297
+ end
298
+
299
+ context "has excluded routes" do
300
+ context "route id matches" do
301
+ it "should return false" do
302
+ @sensor.exclude_forms = true
303
+ @sensor.exclude_cookies = false
304
+ @sensor.excluded_route_ids = {"route_id" => true}
305
+
306
+ expect(TCellAgent).to_not receive(:configuration)
307
+ expect(@sensor).to_not receive(:find_vulnerability)
308
+ expect(@sensor).to_not receive(:send_event)
309
+
310
+ result = @sensor.check(XssSensor::GET_PARAM, @meta, "param_name", "param_value")
311
+
312
+ expect(result).to eq(false)
313
+ end
314
+ end
315
+ context "route id does not match" do
316
+ it "should return false" do
317
+ @sensor.exclude_forms = true
318
+ @sensor.exclude_cookies = false
319
+ @sensor.excluded_route_ids = {"unmatching_route_id" => true}
320
+
321
+ expect(TCellAgent).to_not receive(:configuration)
322
+ expect(@sensor).to_not receive(:find_vulnerability)
323
+ expect(@sensor).to_not receive(:send_event)
324
+
325
+ result = @sensor.check(XssSensor::GET_PARAM, @meta, "param_name", "param_value")
326
+
327
+ expect(result).to eq(false)
328
+ end
329
+ end
330
+ end
238
331
  end
239
332
 
240
333
  context "exclude cookies sensor" do
@@ -497,6 +590,88 @@ module TCellAgent
497
590
  end
498
591
  end
499
592
  end
593
+
594
+ context "no excluded routes" do
595
+ it "should return true" do
596
+ @sensor.exclude_forms = false
597
+ @sensor.exclude_cookies = true
598
+ @sensor.excluded_route_ids = {}
599
+ configuration = double(
600
+ "configuration",
601
+ allow_unencrypted_appfirewall_payloads_logging: false,
602
+ allow_unencrypted_appfirewall_payloads: true,
603
+ blacklisted_params: {},
604
+ whitelist_present: false
605
+ )
606
+
607
+ expect(@sensor).to receive(:find_vulnerability).and_return(
608
+ {"param" => "vuln_param", "value" => "vuln_value", "pattern" => "1"}
609
+ )
610
+ expect(TCellAgent).to receive(:configuration).and_return(configuration).at_least(:once)
611
+ expect(@sensor).to receive(:send_event).with(
612
+ @meta,
613
+ "xss",
614
+ "vuln_param",
615
+ {"t" => XssSensor::GET_PARAM}.to_json,
616
+ "vuln_value",
617
+ "1"
618
+ )
619
+
620
+ result = @sensor.check(XssSensor::GET_PARAM, @meta, "param_name", "param_value")
621
+
622
+ expect(result).to eq(true)
623
+ end
624
+ end
625
+
626
+ context "has excluded routes" do
627
+ context "route id matches" do
628
+ it "should return false" do
629
+ @sensor.exclude_forms = false
630
+ @sensor.exclude_cookies = true
631
+ @sensor.excluded_route_ids = {"route_id" => true}
632
+
633
+ expect(TCellAgent).to_not receive(:configuration)
634
+ expect(@sensor).to_not receive(:find_vulnerability)
635
+ expect(@sensor).to_not receive(:send_event)
636
+
637
+ result = @sensor.check(XssSensor::GET_PARAM, @meta, "param_name", "param_value")
638
+
639
+ expect(result).to eq(false)
640
+ end
641
+ end
642
+
643
+ context "route id does not match" do
644
+ it "should return true" do
645
+ @sensor.exclude_forms = false
646
+ @sensor.exclude_cookies = true
647
+ @sensor.excluded_route_ids = {"unmatching_route_id" => true}
648
+ configuration = double(
649
+ "configuration",
650
+ allow_unencrypted_appfirewall_payloads_logging: false,
651
+ allow_unencrypted_appfirewall_payloads: true,
652
+ blacklisted_params: {},
653
+ whitelist_present: false
654
+ )
655
+
656
+ expect(@sensor).to receive(:find_vulnerability).and_return(
657
+ {"param" => "vuln_param", "value" => "vuln_value", "pattern" => "1"}
658
+ )
659
+ expect(TCellAgent).to receive(:configuration).and_return(configuration).at_least(:once)
660
+ expect(@sensor).to receive(:send_event).with(
661
+ @meta,
662
+ "xss",
663
+ "vuln_param",
664
+ {"t" => XssSensor::GET_PARAM}.to_json,
665
+ "vuln_value",
666
+ "1"
667
+ )
668
+
669
+ result = @sensor.check(XssSensor::GET_PARAM, @meta, "param_name", "param_value")
670
+
671
+ expect(result).to eq(true)
672
+ end
673
+ end
674
+ end
500
675
  end
501
676
  end
502
677