tcell_agent 0.2.29 → 0.4.0

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/Readme.txt +7 -0
  3. data/bin/tcell_agent +9 -0
  4. data/lib/tcell_agent/agent/policy_manager.rb +3 -0
  5. data/lib/tcell_agent/agent/policy_types.rb +4 -1
  6. data/lib/tcell_agent/appsensor/injections_matcher.rb +20 -0
  7. data/lib/tcell_agent/appsensor/injections_reporter.rb +15 -56
  8. data/lib/tcell_agent/appsensor/meta_data.rb +56 -2
  9. data/lib/tcell_agent/appsensor/rules/baserules.json +371 -138
  10. data/lib/tcell_agent/cmdi.rb +113 -0
  11. data/lib/tcell_agent/config/unknown_options.rb +2 -0
  12. data/lib/tcell_agent/configuration.rb +30 -16
  13. data/lib/tcell_agent/hooks/login_fraud.rb +79 -0
  14. data/lib/tcell_agent/instrumentation.rb +6 -11
  15. data/lib/tcell_agent/patches/meta_data.rb +14 -11
  16. data/lib/tcell_agent/policies/appsensor/injection_sensor.rb +5 -9
  17. data/lib/tcell_agent/policies/appsensor_policy.rb +22 -206
  18. data/lib/tcell_agent/policies/clickjacking_policy.rb +4 -2
  19. data/lib/tcell_agent/policies/command_injection_policy.rb +196 -0
  20. data/lib/tcell_agent/policies/content_security_policy.rb +3 -2
  21. data/lib/tcell_agent/policies/dataloss_policy.rb +3 -1
  22. data/lib/tcell_agent/policies/honeytokens_policy.rb +3 -1
  23. data/lib/tcell_agent/policies/http_redirect_policy.rb +51 -37
  24. data/lib/tcell_agent/policies/http_tx_policy.rb +5 -1
  25. data/lib/tcell_agent/policies/login_fraud_policy.rb +6 -1
  26. data/lib/tcell_agent/policies/patches_policy.rb +3 -1
  27. data/lib/tcell_agent/policies/policy.rb +10 -0
  28. data/lib/tcell_agent/policies/secure_headers_policy.rb +5 -2
  29. data/lib/tcell_agent/rails/auth/devise.rb +12 -23
  30. data/lib/tcell_agent/rails/csrf_exception.rb +1 -1
  31. data/lib/tcell_agent/rails/dlp.rb +50 -54
  32. data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +0 -1
  33. data/lib/tcell_agent/rails/middleware/context_middleware.rb +0 -1
  34. data/lib/tcell_agent/rails/middleware/global_middleware.rb +0 -1
  35. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +7 -10
  36. data/lib/tcell_agent/rails/on_start.rb +0 -1
  37. data/lib/tcell_agent/rails/tcell_body_proxy.rb +4 -4
  38. data/lib/tcell_agent/rails.rb +0 -2
  39. data/lib/tcell_agent/rust/libtcellagent-0.6.1.dylib +0 -0
  40. data/lib/tcell_agent/rust/libtcellagent-0.6.1.so +0 -0
  41. data/lib/tcell_agent/rust/models.rb +61 -0
  42. data/lib/tcell_agent/rust/tcellagent-0.6.1.dll +0 -0
  43. data/lib/tcell_agent/rust/whisperer.rb +112 -0
  44. data/lib/tcell_agent/sensor_events/appsensor_event.rb +25 -21
  45. data/lib/tcell_agent/sensor_events/appsensor_meta_event.rb +31 -24
  46. data/lib/tcell_agent/sensor_events/command_injection.rb +58 -0
  47. data/lib/tcell_agent/sensor_events/discovery.rb +1 -1
  48. data/lib/tcell_agent/sensor_events/login_fraud.rb +3 -13
  49. data/lib/tcell_agent/sensor_events/sensor.rb +81 -77
  50. data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +8 -0
  51. data/lib/tcell_agent/start_background_thread.rb +12 -3
  52. data/lib/tcell_agent/utils/io.rb +4 -1
  53. data/lib/tcell_agent/utils/params.rb +1 -0
  54. data/lib/tcell_agent/version.rb +1 -1
  55. data/lib/tcell_agent.rb +0 -1
  56. data/spec/lib/tcell_agent/appsensor/injections_matcher_spec.rb +27 -9
  57. data/spec/lib/tcell_agent/appsensor/injections_reporter_spec.rb +143 -193
  58. data/spec/lib/tcell_agent/appsensor/meta_data_spec.rb +67 -0
  59. data/spec/lib/tcell_agent/appsensor/rules/appsensor_rule_manager_spec.rb +0 -10
  60. data/spec/lib/tcell_agent/cmdi_spec.rb +748 -0
  61. data/spec/lib/tcell_agent/config/unknown_options_spec.rb +8 -0
  62. data/spec/lib/tcell_agent/configuration_spec.rb +138 -6
  63. data/spec/lib/tcell_agent/hooks/login_fraud_spec.rb +357 -0
  64. data/spec/lib/tcell_agent/patches/block_rule_spec.rb +70 -87
  65. data/spec/lib/tcell_agent/patches_spec.rb +9 -4
  66. data/spec/lib/tcell_agent/policies/appsensor/xss_sensor_spec.rb +186 -9
  67. data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +309 -484
  68. data/spec/lib/tcell_agent/policies/command_injection_policy_spec.rb +736 -0
  69. data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +222 -41
  70. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +56 -32
  71. data/spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb +161 -85
  72. data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +40 -72
  73. data/spec/lib/tcell_agent/rust/whisperer_spec.rb +267 -0
  74. data/spec/lib/tcell_agent/sensor_events/appsensor_meta_event_spec.rb +20 -15
  75. data/spec/spec_helper.rb +0 -9
  76. data/tcell_agent.gemspec +8 -3
  77. metadata +40 -39
  78. data/lib/tcell_agent/appsensor/sensor.rb +0 -52
  79. data/lib/tcell_agent/policies/appsensor/database_sensor.rb +0 -56
  80. data/lib/tcell_agent/policies/appsensor/misc_sensor.rb +0 -59
  81. data/lib/tcell_agent/policies/appsensor/payloads_policy.rb +0 -150
  82. data/lib/tcell_agent/policies/appsensor/request_size_sensor.rb +0 -25
  83. data/lib/tcell_agent/policies/appsensor/response_codes_sensor.rb +0 -73
  84. data/lib/tcell_agent/policies/appsensor/response_size_sensor.rb +0 -25
  85. data/lib/tcell_agent/policies/appsensor/size_sensor.rb +0 -71
  86. data/lib/tcell_agent/policies/appsensor/user_agent_sensor.rb +0 -47
  87. data/lib/tcell_agent/rails/auth/hooks.rb +0 -79
  88. data/lib/tcell_agent/sensor_events/util/redirect_utils.rb +0 -22
  89. data/spec/lib/tcell_agent/policies/appsensor/database_sensor_spec.rb +0 -165
  90. data/spec/lib/tcell_agent/policies/appsensor/misc_sensor_spec.rb +0 -429
  91. data/spec/lib/tcell_agent/policies/appsensor/payloads_policy_apply_spec.rb +0 -466
  92. data/spec/lib/tcell_agent/policies/appsensor/payloads_policy_from_json_spec.rb +0 -890
  93. data/spec/lib/tcell_agent/policies/appsensor/payloads_policy_log_spec.rb +0 -417
  94. data/spec/lib/tcell_agent/policies/appsensor/request_size_sensor_spec.rb +0 -236
  95. data/spec/lib/tcell_agent/policies/appsensor/response_codes_sensor_spec.rb +0 -297
  96. data/spec/lib/tcell_agent/policies/appsensor/response_size_sensor_spec.rb +0 -241
  97. data/spec/lib/tcell_agent/policies/appsensor/user_agent_sensor_spec.rb +0 -172
  98. data/spec/lib/tcell_agent/rails/auth/hooks_spec.rb +0 -246
  99. data/spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb +0 -25
  100. data/spec/support/resources/baserules.json +0 -155
@@ -5,566 +5,391 @@ module TCellAgent
5
5
 
6
6
  describe AppSensorPolicy do
7
7
 
8
- describe "#from_json" do
8
+ everything_enabled_policy_json = {
9
+ "policy_id" => "01a1",
10
+ "version" => 2,
11
+ "data" => {
12
+ "options" => {
13
+ "uri_options" => {
14
+ "collect_full_uri" => true
15
+ },
16
+ "payloads" => {
17
+ "send_payloads" => true,
18
+ "send_blacklist" => {
19
+ "ssn" => ["*"],
20
+ "password" => ["*"]
21
+ },
22
+ "send_whitelist" => {},
23
+ "log_payloads" => true,
24
+ "log_blacklist" => {},
25
+ "log_whitelist" => {
26
+ "username" => ["*"]
27
+ }
28
+ }
29
+ },
30
+ "sensors" => {
31
+ "req_size" => {
32
+ "limit" => 1024,
33
+ "exclude_routes" => ["2300"]
34
+ },
35
+ "resp_size" => {
36
+ "limit" => 2048,
37
+ "exclude_routes" => ["2323"]
38
+ },
39
+ "resp_codes" => {
40
+ "series_400_enabled" => true,
41
+ "series_500_enabled" => true
42
+ },
43
+ "xss" => {
44
+ "libinjection" => true,
45
+ "patterns" => ["1","2","8"],
46
+ "exclusions" => {
47
+ "bob" => ["*"]
48
+ }
49
+ },
50
+ "sqli" => {
51
+ "libinjection" => true,
52
+ "exclude_headers" => true,
53
+ "patterns" => ["1"]
54
+ },
55
+ "fpt" => {
56
+ "patterns" => ["1","2"],
57
+ "exclude_forms" => true,
58
+ "exclude_cookies" => true,
59
+ "exclusions" => {
60
+ "somethingcommon" => ["form"]
61
+ }
62
+ },
63
+ "cmdi" => {
64
+ "patterns" => ["1","2"]
65
+ },
66
+ "nullbyte" => {
67
+ "patterns" => ["1","2"]
68
+ },
69
+ "retr" => {
70
+ "patterns" => ["1","2"]
71
+ },
72
+ "ua" => {
73
+ "empty_enabled" => true,
74
+ },
75
+ "errors" => {
76
+ "csrf_exception_enabled" => true,
77
+ "sql_exception_enabled" => true
78
+ },
79
+ "database" => {
80
+ "large_result" => {
81
+ "limit" => 10
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
9
87
 
10
- context "with v1 policy" do
88
+ describe "#from_json" do
89
+ context "with v2 policy" do
11
90
  context "that is missing a policy id" do
12
- it "should raise an error" do
13
- expect{
14
- AppSensorPolicy.from_json({
15
- "data" => { "options" => {} }
16
- })
17
- }.to raise_error(RuntimeError)
91
+ it "should have appfirewall disabled" do
92
+ policy = AppSensorPolicy.from_json({
93
+ "version" => 2,
94
+ "data" => { }
95
+ })
96
+
97
+ expect(policy.appfirewall_enabled).to eq(false)
98
+ expect(policy.appfirewall_ptr).to be_nil
18
99
  end
19
100
  end
20
101
 
21
- context "that has empty options" do
22
- it "should have all sensors disabled" do
23
- expect_any_instance_of(AppSensorRuleManager).to_not receive(:instance)
24
-
25
- policy_json_empty = {
102
+ context "that is missing a version id" do
103
+ it "should have appfirewall disabled" do
104
+ policy = AppSensorPolicy.from_json({
26
105
  "policy_id" => "01a1",
27
- "data" => {
28
- "options"=> {}
29
- }
30
- }
31
-
32
- empty_policy = AppSensorPolicy.from_json(policy_json_empty)
106
+ "data" => { }
107
+ })
33
108
 
34
- expect(empty_policy.policy_id).to eq("01a1")
35
- expect(empty_policy.enabled).to eq(false)
36
- expect(empty_policy.injections_reporter.payloads_policy).to_not be_nil
37
- expect(empty_policy.injections_reporter.payloads_policy.send_payloads).to eq(false)
38
- expect(empty_policy.injections_reporter.payloads_policy.log_payloads).to eq(false)
39
- expect(empty_policy.options["req_size"]).to be_nil
40
- expect(empty_policy.options["resp_size"]).to be_nil
41
- expect(empty_policy.options["resp_codes"]).to be_nil
42
- expect(empty_policy.options["xss"]).to be_nil
43
- expect(empty_policy.options["sqli"]).to be_nil
44
- expect(empty_policy.options["cmdi"]).to be_nil
45
- expect(empty_policy.options["fpt"]).to be_nil
46
- expect(empty_policy.options["nullbyte"]).to be_nil
47
- expect(empty_policy.options["retr"]).to be_nil
48
- expect(empty_policy.options["ua"]).to be_nil
49
- expect(empty_policy.options["errors"]).to be_nil
50
- expect(empty_policy.options["database"]).to be_nil
109
+ expect(policy.appfirewall_enabled).to eq(false)
110
+ expect(policy.appfirewall_ptr).to be_nil
51
111
  end
52
112
  end
53
113
 
54
- context "that has no options" do
114
+ context "that has no sensors" do
55
115
  it "should have all sensors disabled" do
56
- expect(AppSensorRuleManager).to_not receive(:instance)
57
-
58
116
  policy_json_empty = {
59
117
  "policy_id" => "01a1",
118
+ "version" => 2,
60
119
  "data" => {
61
120
  }
62
121
  }
63
122
 
64
123
  empty_policy = AppSensorPolicy.from_json(policy_json_empty)
65
124
 
66
- expect(empty_policy.policy_id).to eq("01a1")
67
- expect(empty_policy.enabled).to eq(false)
68
- expect(empty_policy.injections_reporter.payloads_policy).to_not be_nil
69
- expect(empty_policy.injections_reporter.payloads_policy.send_payloads).to eq(false)
70
- expect(empty_policy.injections_reporter.payloads_policy.log_payloads).to eq(false)
71
- expect(empty_policy.options["req_size"]).to be_nil
72
- expect(empty_policy.options["resp_size"]).to be_nil
73
- expect(empty_policy.options["resp_codes"]).to be_nil
74
- expect(empty_policy.options["xss"]).to be_nil
75
- expect(empty_policy.options["sqli"]).to be_nil
76
- expect(empty_policy.options["cmdi"]).to be_nil
77
- expect(empty_policy.options["fpt"]).to be_nil
78
- expect(empty_policy.options["nullbyte"]).to be_nil
79
- expect(empty_policy.options["retr"]).to be_nil
80
- expect(empty_policy.options["ua"]).to be_nil
81
- expect(empty_policy.options["errors"]).to be_nil
82
- expect(empty_policy.options["database"]).to be_nil
125
+ expect(empty_policy.appfirewall_enabled).to eq(false)
126
+ expect(empty_policy.appfirewall_ptr).to_not be_nil
83
127
  end
84
128
  end
85
129
 
86
- context "that only has null enabled" do
87
- it "should only have null enabled" do
88
- expect(AppSensorRuleManager).to receive(:instance)
89
-
90
- policy_json = {
130
+ context "that has empty sensors" do
131
+ it "should have all sensors disabled" do
132
+ policy_json_empty = {
91
133
  "policy_id" => "01a1",
134
+ "version" => 2,
92
135
  "data" => {
93
- "options"=> {"null"=>true}
136
+ "sensors" => {}
94
137
  }
95
138
  }
96
139
 
97
- policy = AppSensorPolicy.from_json(policy_json)
140
+ empty_policy = AppSensorPolicy.from_json(policy_json_empty)
98
141
 
99
- expect(policy.policy_id).to eq("01a1")
100
- expect(policy.enabled).to eq(true)
101
- expect(policy.injections_reporter.payloads_policy).to_not be_nil
102
- expect(policy.injections_reporter.payloads_policy.send_payloads).to eq(true)
103
- expect(policy.injections_reporter.payloads_policy.log_payloads).to eq(true)
104
- expect(policy.options["req_size"]).to_not be_nil
105
- expect(policy.options["resp_size"]).to_not be_nil
106
- expect(policy.options["resp_codes"]).to_not be_nil
107
- expect(policy.options["ua"]).to_not be_nil
108
- expect(policy.options["errors"]).to_not be_nil
109
- expect(policy.options["database"]).to_not be_nil
110
-
111
- injections_matcher = policy.injections_reporter.injections_matcher
112
- expect(injections_matcher).to_not be_nil
113
- expect(injections_matcher.sensors.size).to eq(1)
114
- expect(injections_matcher.sensors[0].detection_point).to eq("null")
115
- expect(injections_matcher.sensors[0].enabled).to eq(true)
116
- expect(injections_matcher.sensors[0].v1_compatability_enabled).to eq(true)
142
+ expect(empty_policy.appfirewall_enabled).to eq(true)
143
+ expect(empty_policy.appfirewall_ptr).to_not be_nil
117
144
  end
118
145
  end
119
146
 
120
147
  context "that only has xss enabled" do
121
- it "should only have xss enabled" do
122
- expect(AppSensorRuleManager).to receive(:instance)
123
-
148
+ it "should be enabled" do
124
149
  policy_json = {
125
150
  "policy_id" => "01a1",
151
+ "version" => 2,
126
152
  "data" => {
127
- "options"=> {"xss"=>true}
153
+ "sensors" => {
154
+ "xss" => {
155
+ "libinjection" => true,
156
+ "patterns" => ["1","2","8"],
157
+ "exclusions" => {
158
+ "bob" => ["*"]
159
+ }
160
+ }
161
+ }
128
162
  }
129
163
  }
130
164
 
131
- empty_policy = AppSensorPolicy.from_json(policy_json)
132
-
133
- expect(empty_policy.policy_id).to eq("01a1")
134
- expect(empty_policy.enabled).to eq(true)
135
- expect(empty_policy.injections_reporter.payloads_policy.send_payloads).to eq(true)
136
- expect(empty_policy.injections_reporter.payloads_policy.log_payloads).to eq(true)
137
- expect(empty_policy.options["req_size"]).to_not be_nil
138
- expect(empty_policy.options["resp_size"]).to_not be_nil
139
- expect(empty_policy.options["resp_codes"]).to_not be_nil
140
- expect(empty_policy.options["ua"]).to_not be_nil
141
- expect(empty_policy.options["errors"]).to_not be_nil
142
- expect(empty_policy.options["database"]).to_not be_nil
143
-
144
- expect(empty_policy.options["req_size"].enabled).to eq(false)
145
- expect(empty_policy.options["resp_size"].enabled).to eq(false)
146
- expect(empty_policy.options["resp_codes"].enabled).to eq(false)
147
- expect(empty_policy.options["ua"].enabled).to eq(false)
148
- expect(empty_policy.options["ua"].empty_enabled).to eq(false)
149
- expect(empty_policy.options["errors"].enabled).to eq(false)
150
- expect(empty_policy.options["errors"].csrf_exception_enabled).to eq(false)
151
- expect(empty_policy.options["errors"].sql_exception_enabled).to eq(false)
152
- expect(empty_policy.options["database"].enabled).to eq(false)
153
-
154
- injections_matcher = empty_policy.injections_reporter.injections_matcher
155
- expect(injections_matcher).to_not be_nil
156
- expect(injections_matcher.sensors.size).to eq(1)
157
- expect(injections_matcher.sensors[0].detection_point).to eq("xss")
158
- expect(injections_matcher.sensors[0].enabled).to eq(true)
159
- expect(injections_matcher.sensors[0].v1_compatability_enabled).to eq(true)
165
+ policy = AppSensorPolicy.from_json(policy_json)
166
+
167
+ expect(policy.appfirewall_enabled).to eq(true)
168
+ expect(policy.appfirewall_ptr).to_not be_nil
160
169
  end
161
170
  end
162
171
 
163
172
  context "that has everything enabled" do
164
- it "should have all sensors enabled" do
165
- expect(AppSensorRuleManager).to receive(:instance).exactly(6).times
173
+ it "should be enabled" do
174
+ policy = AppSensorPolicy.from_json(everything_enabled_policy_json)
166
175
 
167
- policy_json = {
168
- "policy_id" => "01a1",
169
- "data" => {
170
- "options"=> {
171
- "req_res_size"=>true,
172
- "resp_codes"=>true,
173
- "xss"=>true,
174
- "sqli"=>true,
175
- "cmdi"=>true,
176
- "fpt"=>true,
177
- "null"=>true,
178
- "retr"=>true
179
- }
180
- }
181
- }
182
-
183
- policy = AppSensorPolicy.from_json(policy_json)
184
-
185
- expect(policy.policy_id).to eq("01a1")
186
- expect(policy.enabled).to eq(true)
187
- expect(policy.injections_reporter.payloads_policy.send_payloads).to eq(true)
188
- expect(policy.injections_reporter.payloads_policy.log_payloads).to eq(true)
189
- expect(policy.options["req_size"]).to_not be_nil
190
- expect(policy.options["resp_size"]).to_not be_nil
191
- expect(policy.options["resp_codes"]).to_not be_nil
192
-
193
- expect(policy.options["ua"]).to_not be_nil
194
- expect(policy.options["errors"]).to_not be_nil
195
- expect(policy.options["database"]).to_not be_nil
196
-
197
- expect(policy.options["req_size"].enabled).to eq(true)
198
- expect(policy.options["resp_size"].enabled).to eq(true)
199
- expect(policy.options["resp_codes"].enabled).to eq(true)
200
- expect(policy.options["ua"].enabled).to eq(false)
201
- expect(policy.options["ua"].empty_enabled).to eq(false)
202
- expect(policy.options["errors"].enabled).to eq(false)
203
- expect(policy.options["errors"].csrf_exception_enabled).to eq(false)
204
- expect(policy.options["errors"].sql_exception_enabled).to eq(false)
205
- expect(policy.options["database"].enabled).to eq(false)
206
-
207
- injections_matcher = policy.injections_reporter.injections_matcher
208
- expect(injections_matcher).to_not be_nil
209
- expect(injections_matcher.sensors.size).to eq(6)
210
-
211
- sorted_sensors = injections_matcher.sensors.sort do
212
- |a,b| a.detection_point <=> b.detection_point
213
- end
214
- expect(sorted_sensors[0].detection_point).to eq("cmdi")
215
- expect(sorted_sensors[0].enabled).to eq(true)
216
- expect(sorted_sensors[0].v1_compatability_enabled).to eq(true)
217
- expect(sorted_sensors[1].detection_point).to eq("fpt")
218
- expect(sorted_sensors[1].enabled).to eq(true)
219
- expect(sorted_sensors[1].v1_compatability_enabled).to eq(true)
220
- expect(sorted_sensors[2].detection_point).to eq("null")
221
- expect(sorted_sensors[2].enabled).to eq(true)
222
- expect(sorted_sensors[2].v1_compatability_enabled).to eq(true)
223
- expect(sorted_sensors[3].detection_point).to eq("retr")
224
- expect(sorted_sensors[3].enabled).to eq(true)
225
- expect(sorted_sensors[3].v1_compatability_enabled).to eq(true)
226
- expect(sorted_sensors[4].detection_point).to eq("sqli")
227
- expect(sorted_sensors[4].enabled).to eq(true)
228
- expect(sorted_sensors[4].v1_compatability_enabled).to eq(true)
229
- expect(sorted_sensors[5].detection_point).to eq("xss")
230
- expect(sorted_sensors[5].enabled).to eq(true)
231
- expect(sorted_sensors[5].v1_compatability_enabled).to eq(true)
176
+ expect(policy.appfirewall_enabled).to eq(true)
177
+ expect(policy.appfirewall_ptr).to_not be_nil
232
178
  end
233
179
  end
234
180
  end
181
+ end
235
182
 
236
- context "with v2 policy" do
237
- context "that is missing a policy id" do
238
- it "should raise an error" do
239
- expect{
240
- AppSensorPolicy.from_json({
241
- "version" => 2,
242
- "data" => { }
243
- })
244
- }.to raise_error(RuntimeError)
245
- end
183
+ describe "#process_meta_event" do
184
+ context "with everything enabled policy" do
185
+ before(:each) do
186
+ @policy = AppSensorPolicy.from_json(everything_enabled_policy_json)
187
+ @appsensor_meta = TCellAgent::SensorEvents::AppSensorMetaEvent.new(
188
+ "get",
189
+ "remote_address",
190
+ "route_id",
191
+ "session_id",
192
+ "user_id",
193
+ "transaction_id")
194
+ @appsensor_meta.user_agent = "Mozilla"
195
+ @appsensor_meta.response_code = 200
246
196
  end
247
197
 
248
- context "that has no sensors" do
249
- it "should have all sensors disabled" do
250
- expect(AppSensorRuleManager).to_not receive(:instance)
198
+ context "csrf exception" do
199
+ context "nil csrf exception" do
200
+ it "should not send an event" do
201
+ expect(TCellAgent).to_not receive(:send_event)
251
202
 
252
- policy_json_empty = {
253
- "policy_id" => "01a1",
254
- "version" => 2,
255
- "data" => {
256
- }
257
- }
258
-
259
- empty_policy = AppSensorPolicy.from_json(policy_json_empty)
260
-
261
- expect(empty_policy.policy_id).to eq("01a1")
262
- expect(empty_policy.enabled).to eq(false)
263
- expect(empty_policy.injections_reporter.payloads_policy).to_not be_nil
264
- expect(empty_policy.injections_reporter.payloads_policy.send_payloads).to eq(false)
265
- expect(empty_policy.injections_reporter.payloads_policy.log_payloads).to eq(false)
266
- expect(empty_policy.options["req_size"]).to be_nil
267
- expect(empty_policy.options["resp_size"]).to be_nil
268
- expect(empty_policy.options["resp_codes"]).to be_nil
269
- expect(empty_policy.options["ua"]).to be_nil
270
- expect(empty_policy.options["errors"]).to be_nil
271
- expect(empty_policy.options["database"]).to be_nil
272
-
273
- injections_matcher = empty_policy.injections_reporter.injections_matcher
274
- expect(injections_matcher).to_not be_nil
275
- expect(injections_matcher.sensors.size).to eq(0)
203
+ @appsensor_meta.csrf_exception_name = nil
204
+ @policy.process_meta_event(
205
+ @appsensor_meta
206
+ )
207
+ end
276
208
  end
277
- end
278
209
 
279
- context "that has empty sensors" do
280
- it "should have all sensors disabled" do
281
- expect(AppSensorRuleManager).to_not receive(:instance)
210
+ context "empty csrf exception" do
211
+ it "should not send an event" do
212
+ expect(TCellAgent).to_not receive(:send_event)
282
213
 
283
- policy_json_empty = {
284
- "policy_id" => "01a1",
285
- "version" => 2,
286
- "data" => {
287
- "sensors" => {}
288
- }
289
- }
214
+ @appsensor_meta.csrf_exception_name = ""
215
+ @policy.process_meta_event(
216
+ @appsensor_meta
217
+ )
218
+ end
219
+ end
290
220
 
291
- empty_policy = AppSensorPolicy.from_json(policy_json_empty)
221
+ context "one csrf exception" do
222
+ it "should send a csrf exception event" do
223
+ expect(TCellAgent).to receive(:send_event).with({
224
+ "event_type" => "as",
225
+ "dp" => "excsrf",
226
+ "param" => "ActionController::InvalidAuthenticityToken",
227
+ "m" => "get",
228
+ "rid" => "route_id",
229
+ "uid" => "user_id",
230
+ "sid" => "session_id",
231
+ "remote_addr" => "remote_address"
232
+ })
292
233
 
293
- expect(empty_policy.policy_id).to eq("01a1")
294
- expect(empty_policy.enabled).to eq(false)
295
- expect(empty_policy.injections_reporter.payloads_policy).to_not be_nil
296
- expect(empty_policy.injections_reporter.payloads_policy.send_payloads).to eq(false)
297
- expect(empty_policy.injections_reporter.payloads_policy.log_payloads).to eq(false)
298
- expect(empty_policy.options["req_size"]).to be_nil
299
- expect(empty_policy.options["resp_size"]).to be_nil
300
- expect(empty_policy.options["resp_codes"]).to be_nil
301
- expect(empty_policy.options["ua"]).to be_nil
302
- expect(empty_policy.options["errors"]).to be_nil
303
- expect(empty_policy.options["database"]).to be_nil
304
-
305
- injections_matcher = empty_policy.injections_reporter.injections_matcher
306
- expect(injections_matcher).to_not be_nil
307
- expect(injections_matcher.sensors.size).to eq(0)
234
+ @appsensor_meta.csrf_exception_name = "ActionController::InvalidAuthenticityToken"
235
+ @policy.process_meta_event(
236
+ @appsensor_meta
237
+ )
238
+ end
308
239
  end
309
240
  end
310
241
 
311
- context "that only has null enabled" do
312
- it "should only have null enabled" do
313
- expect(AppSensorRuleManager).to receive(:instance)
242
+ context "sql exception" do
243
+ context "empty sql exceptions" do
244
+ it "should not send an event" do
245
+ expect(TCellAgent).to_not receive(:send_event)
314
246
 
315
- policy_json = {
316
- "policy_id" => "01a1",
317
- "version" => 2,
318
- "data" => {
319
- "sensors" => {
320
- "nullbyte" => {
321
- "patterns" => ["1","2"]
322
- }
323
- }
324
- }
325
- }
247
+ @appsensor_meta.sql_exceptions = []
248
+ @policy.process_meta_event(
249
+ @appsensor_meta
250
+ )
251
+ end
252
+ end
326
253
 
327
- policy = AppSensorPolicy.from_json(policy_json)
254
+ context "one sql exception" do
255
+ it "should send one event" do
256
+ expect(TCellAgent).to receive(:send_event).with({
257
+ "event_type" => "as",
258
+ "dp" => "exsql",
259
+ "param" => "ActiveRecord::StatementInvalid",
260
+ "m" => "get",
261
+ "rid" => "route_id",
262
+ "uid" => "user_id",
263
+ "sid" => "session_id",
264
+ "remote_addr" => "remote_address",
265
+ "payload" => "exception message goes here"
266
+ })
328
267
 
329
- expect(policy.policy_id).to eq("01a1")
330
- expect(policy.injections_reporter.payloads_policy).to_not be_nil
331
- expect(policy.injections_reporter.payloads_policy.send_payloads).to eq(false)
332
- expect(policy.injections_reporter.payloads_policy.log_payloads).to eq(false)
333
- expect(policy.options["req_size"]).to_not be_nil
334
- expect(policy.options["resp_size"]).to_not be_nil
335
- expect(policy.options["resp_codes"]).to_not be_nil
336
-
337
- expect(policy.options["ua"]).to_not be_nil
338
- expect(policy.options["errors"]).to_not be_nil
339
- expect(policy.options["database"]).to_not be_nil
340
-
341
- expect(policy.options["req_size"].enabled).to eq(false)
342
- expect(policy.options["resp_size"].enabled).to eq(false)
343
- expect(policy.options["resp_codes"].enabled).to eq(false)
344
- expect(policy.options["ua"].enabled).to eq(false)
345
- expect(policy.options["ua"].empty_enabled).to eq(false)
346
- expect(policy.options["errors"].enabled).to eq(false)
347
- expect(policy.options["errors"].csrf_exception_enabled).to eq(false)
348
- expect(policy.options["errors"].sql_exception_enabled).to eq(false)
349
- expect(policy.options["database"].enabled).to eq(false)
350
-
351
- injections_matcher = policy.injections_reporter.injections_matcher
352
- expect(injections_matcher).to_not be_nil
353
- expect(injections_matcher.sensors.size).to eq(1)
354
- expect(injections_matcher.sensors[0].detection_point).to eq("null")
355
- expect(injections_matcher.sensors[0].enabled).to eq(true)
356
- expect(injections_matcher.sensors[0].v1_compatability_enabled).to eq(false)
268
+ @appsensor_meta.sql_exceptions = [{
269
+ "exception_name" => "ActiveRecord::StatementInvalid",
270
+ "exception_payload" => "exception message goes here"
271
+ }]
272
+ @policy.process_meta_event(
273
+ @appsensor_meta
274
+ )
275
+ end
357
276
  end
358
- end
359
277
 
360
- context "that only has xss enabled" do
361
- it "should only have xss enabled" do
362
- expect(AppSensorRuleManager).to receive(:instance)
278
+ context "multiple sql exception" do
279
+ it "should send multiple event" do
280
+ expect(TCellAgent).to receive(:send_event).with({
281
+ "event_type" => "as",
282
+ "dp" => "exsql",
283
+ "param" => "ActiveRecord::StatementInvalid",
284
+ "m" => "get",
285
+ "rid" => "route_id",
286
+ "uid" => "user_id",
287
+ "sid" => "session_id",
288
+ "remote_addr" => "remote_address",
289
+ "payload" => "exception message goes here"
290
+ })
291
+ expect(TCellAgent).to receive(:send_event).with({
292
+ "event_type" => "as",
293
+ "dp" => "exsql",
294
+ "param" => "ActiveRecord::StatementInvalid",
295
+ "m" => "get",
296
+ "rid" => "route_id",
297
+ "uid" => "user_id",
298
+ "sid" => "session_id",
299
+ "remote_addr" => "remote_address",
300
+ "payload" => "second exception message goes here"
301
+ })
363
302
 
364
- policy_json = {
365
- "policy_id" => "01a1",
366
- "version" => 2,
367
- "data" => {
368
- "sensors" => {
369
- "xss" => {
370
- "libinjection" => true,
371
- "patterns" => ["1","2","8"],
372
- "exclusions" => {
373
- "bob" => ["*"]
374
- }
375
- }
303
+ @appsensor_meta.sql_exceptions = [
304
+ {
305
+ "exception_name" => "ActiveRecord::StatementInvalid",
306
+ "exception_payload" => "exception message goes here"
307
+ },
308
+ {
309
+ "exception_name" => "ActiveRecord::StatementInvalid",
310
+ "exception_payload" => "second exception message goes here"
376
311
  }
377
- }
378
- }
312
+ ]
313
+ @policy.process_meta_event(
314
+ @appsensor_meta
315
+ )
316
+ end
317
+ end
318
+ end
379
319
 
380
- policy = AppSensorPolicy.from_json(policy_json)
320
+ context "db max result" do
321
+ context "nil db max result" do
322
+ it "should not send an event" do
323
+ expect(TCellAgent).to_not receive(:send_event)
381
324
 
382
- expect(policy.policy_id).to eq("01a1")
383
- expect(policy.injections_reporter.payloads_policy).to_not be_nil
384
- expect(policy.injections_reporter.payloads_policy.send_payloads).to eq(false)
385
- expect(policy.injections_reporter.payloads_policy.log_payloads).to eq(false)
386
- expect(policy.options["req_size"]).to_not be_nil
387
- expect(policy.options["resp_size"]).to_not be_nil
388
- expect(policy.options["resp_codes"]).to_not be_nil
389
- expect(policy.options["ua"]).to_not be_nil
390
- expect(policy.options["errors"]).to_not be_nil
391
- expect(policy.options["database"]).to_not be_nil
392
-
393
- expect(policy.options["req_size"].enabled).to eq(false)
394
- expect(policy.options["resp_size"].enabled).to eq(false)
395
- expect(policy.options["resp_codes"].enabled).to eq(false)
396
- expect(policy.options["ua"].enabled).to eq(false)
397
- expect(policy.options["ua"].empty_enabled).to eq(false)
398
- expect(policy.options["errors"].enabled).to eq(false)
399
- expect(policy.options["errors"].csrf_exception_enabled).to eq(false)
400
- expect(policy.options["errors"].sql_exception_enabled).to eq(false)
401
- expect(policy.options["database"].enabled).to eq(false)
402
-
403
- injections_matcher = policy.injections_reporter.injections_matcher
404
- expect(injections_matcher).to_not be_nil
405
- expect(injections_matcher.sensors.size).to eq(1)
406
- expect(injections_matcher.sensors[0].detection_point).to eq("xss")
407
- expect(injections_matcher.sensors[0].enabled).to eq(true)
408
- expect(injections_matcher.sensors[0].v1_compatability_enabled).to eq(false)
325
+ @appsensor_meta.database_result_sizes = nil
326
+ @policy.process_meta_event(
327
+ @appsensor_meta
328
+ )
329
+ end
409
330
  end
410
- end
411
331
 
412
- context "that has everything enabled" do
413
- it "should have all sensors enabled" do
414
- expect(AppSensorRuleManager).to receive(:instance).exactly(6).times
332
+ context "empty db max result" do
333
+ it "should not send an event" do
334
+ expect(TCellAgent).to_not receive(:send_event)
415
335
 
416
- policy_json = {
417
- "policy_id" => "01a1",
418
- "version" => 2,
419
- "data" => {
420
- "options" => {
421
- "uri_options" => {
422
- "collect_full_uri" => true
423
- },
424
- "payloads" => {
425
- "send_payloads" => true,
426
- "send_blacklist" => {
427
- "JSESSIONID" => ["cookie"],
428
- "ssn" => ["*"],
429
- "password" => ["*"]
430
- },
431
- "send_whitelist" => {},
432
- "log_payloads" => true,
433
- "log_blacklist" => {},
434
- "log_whitelist" => {
435
- "username" => ["*"]
436
- }
437
- }
438
- },
439
- "sensors" => {
440
- "req_size" => {
441
- "limit" => 1024,
442
- "exclude_routes" => ["2300"]
443
- },
444
- "resp_size" => {
445
- "limit" => 2048,
446
- "exclude_routes" => ["2323"]
447
- },
448
- "resp_codes" => {
449
- "series_400_enabled" => true,
450
- "series_500_enabled" => true
451
- },
452
- "xss" => {
453
- "libinjection" => true,
454
- "patterns" => ["1","2","8"],
455
- "exclusions" => {
456
- "bob" => ["*"]
457
- }
458
- },
459
- "sqli" => {
460
- "libinjection" => true,
461
- "exclude_headers" => true,
462
- "patterns" => ["1"]
463
- },
464
- "fpt" => {
465
- "patterns" => ["1","2"],
466
- "exclude_forms" => true,
467
- "exclude_cookies" => true,
468
- "exclusions" => {
469
- "somethingcommon" => ["form"]
470
- }
471
- },
472
- "cmdi" => {
473
- "patterns" => ["1","2"]
474
- },
475
- "nullbyte" => {
476
- "patterns" => ["1","2"]
477
- },
478
- "retr" => {
479
- "patterns" => ["1","2"]
480
- },
481
- "ua" => {
482
- "empty_enabled" => true,
483
- },
484
- "errors" => {
485
- "csrf_exception_enabled" => true,
486
- "sql_exception_enabled" => true
487
- },
488
- "database" => {
489
- "large_result" => {
490
- "limit" => 10
491
- }
492
- }
493
- }
494
- }
495
- }
336
+ @appsensor_meta.database_result_sizes = []
337
+ @policy.process_meta_event(
338
+ @appsensor_meta
339
+ )
340
+ end
341
+ end
496
342
 
497
- policy = AppSensorPolicy.from_json(policy_json)
343
+ context "one db max result" do
344
+ it "should send one event" do
345
+ expect(TCellAgent).to receive(:send_event).with({
346
+ "event_type" => "as",
347
+ "dp" => "dbmaxrows",
348
+ "m" => "get",
349
+ "meta" => {"rows"=>1001},
350
+ "rid" => "route_id",
351
+ "uid" => "user_id",
352
+ "sid" => "session_id",
353
+ "remote_addr" => "remote_address"
354
+ })
498
355
 
499
- expect(policy.policy_id).to eq("01a1")
500
- expect(policy.injections_reporter.payloads_policy).to_not be_nil
501
- expect(policy.options["req_size"]).to_not be_nil
502
- expect(policy.options["resp_size"]).to_not be_nil
503
- expect(policy.options["resp_codes"]).to_not be_nil
504
-
505
- expect(policy.options["ua"]).to_not be_nil
506
- expect(policy.options["errors"]).to_not be_nil
507
- expect(policy.options["database"]).to_not be_nil
508
-
509
- expect(policy.options["req_size"].enabled).to eq(true)
510
- expect(policy.options["req_size"].collect_full_uri).to eq(true)
511
- expect(policy.options["resp_size"].enabled).to eq(true)
512
- expect(policy.options["resp_size"].collect_full_uri).to eq(true)
513
- expect(policy.options["resp_codes"].enabled).to eq(true)
514
- expect(policy.options["resp_codes"].collect_full_uri).to eq(true)
515
- expect(policy.options["ua"].enabled).to eq(true)
516
- expect(policy.options["ua"].empty_enabled).to eq(true)
517
- expect(policy.options["ua"].collect_full_uri).to eq(true)
518
- expect(policy.options["errors"].enabled).to eq(true)
519
- expect(policy.options["errors"].csrf_exception_enabled).to eq(true)
520
- expect(policy.options["errors"].sql_exception_enabled).to eq(true)
521
- expect(policy.options["errors"].collect_full_uri).to eq(true)
522
- expect(policy.options["database"].enabled).to eq(true)
523
- expect(policy.options["database"].max_rows).to eq(10)
524
- expect(policy.options["database"].collect_full_uri).to eq(true)
525
-
526
- expect(policy.injections_reporter.collect_full_uri).to eq(true)
527
- expect(policy.injections_reporter.payloads_policy.send_payloads).to eq(true)
528
- expect(policy.injections_reporter.payloads_policy.send_blacklist).to eq({
529
- "jsessionid" => Set.new(["cookie"]),
530
- "ssn" => Set.new(["*"]),
531
- "password" => Set.new(["*"])
532
- })
533
- expect(policy.injections_reporter.payloads_policy.use_send_whitelist).to eq(true)
534
- expect(policy.injections_reporter.payloads_policy.send_whitelist).to eq({})
535
- expect(policy.injections_reporter.payloads_policy.log_payloads).to eq(true)
536
- expect(policy.injections_reporter.payloads_policy.log_blacklist).to eq({})
537
- expect(policy.injections_reporter.payloads_policy.use_log_whitelist).to eq(true)
538
- expect(policy.injections_reporter.payloads_policy.log_whitelist).to eq({
539
- "username" => Set.new(["*"]),
540
- })
541
- expect(policy.injections_reporter.payloads_policy.collect_full_uri).to eq(true)
356
+ @appsensor_meta.database_result_sizes = [1001]
357
+ @policy.process_meta_event(
358
+ @appsensor_meta
359
+ )
360
+ end
361
+ end
542
362
 
543
- injections_matcher = policy.injections_reporter.injections_matcher
544
- sorted_sensors = injections_matcher.sensors.sort do
545
- |a,b| a.detection_point <=> b.detection_point
363
+ context "multiple db max results" do
364
+ it "should send multiple event" do
365
+ expect(TCellAgent).to receive(:send_event).with({
366
+ "event_type" => "as",
367
+ "dp" => "dbmaxrows",
368
+ "m" => "get",
369
+ "meta" => {"rows"=>1001},
370
+ "rid" => "route_id",
371
+ "uid" => "user_id",
372
+ "sid" => "session_id",
373
+ "remote_addr" => "remote_address"
374
+ })
375
+ expect(TCellAgent).to receive(:send_event).with({
376
+ "event_type" => "as",
377
+ "dp" => "dbmaxrows",
378
+ "m" => "get",
379
+ "meta" => {"rows"=>1002},
380
+ "rid" => "route_id",
381
+ "uid" => "user_id",
382
+ "sid" => "session_id",
383
+ "remote_addr" => "remote_address"
384
+ })
385
+
386
+ @appsensor_meta.database_result_sizes = [1001, 1002]
387
+ @policy.process_meta_event(
388
+ @appsensor_meta
389
+ )
546
390
  end
547
- expect(sorted_sensors[0].detection_point).to eq("cmdi")
548
- expect(sorted_sensors[0].enabled).to eq(true)
549
- expect(sorted_sensors[0].v1_compatability_enabled).to eq(false)
550
- expect(sorted_sensors[1].detection_point).to eq("fpt")
551
- expect(sorted_sensors[1].enabled).to eq(true)
552
- expect(sorted_sensors[1].v1_compatability_enabled).to eq(false)
553
- expect(sorted_sensors[2].detection_point).to eq("null")
554
- expect(sorted_sensors[2].enabled).to eq(true)
555
- expect(sorted_sensors[2].v1_compatability_enabled).to eq(false)
556
- expect(sorted_sensors[3].detection_point).to eq("retr")
557
- expect(sorted_sensors[3].enabled).to eq(true)
558
- expect(sorted_sensors[3].v1_compatability_enabled).to eq(false)
559
- expect(sorted_sensors[4].detection_point).to eq("sqli")
560
- expect(sorted_sensors[4].enabled).to eq(true)
561
- expect(sorted_sensors[4].v1_compatability_enabled).to eq(false)
562
- expect(sorted_sensors[5].detection_point).to eq("xss")
563
- expect(sorted_sensors[5].enabled).to eq(true)
564
- expect(sorted_sensors[5].v1_compatability_enabled).to eq(false)
565
391
  end
566
392
  end
567
-
568
393
  end
569
394
  end
570
395
  end