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
@@ -1,231 +1,47 @@
1
1
  require 'tcell_agent/instrumentation'
2
2
  require 'tcell_agent/appsensor/injections_reporter'
3
- require 'tcell_agent/policies/appsensor/cmdi_sensor'
4
- require 'tcell_agent/policies/appsensor/database_sensor'
5
- require 'tcell_agent/policies/appsensor/fpt_sensor'
6
- require 'tcell_agent/policies/appsensor/misc_sensor'
7
- require 'tcell_agent/policies/appsensor/nullbyte_sensor'
8
- require 'tcell_agent/policies/appsensor/payloads_policy'
9
- require 'tcell_agent/policies/appsensor/request_size_sensor'
10
- require 'tcell_agent/policies/appsensor/response_codes_sensor'
11
- require 'tcell_agent/policies/appsensor/response_size_sensor'
12
- require 'tcell_agent/policies/appsensor/retr_sensor'
13
- require 'tcell_agent/policies/appsensor/sqli_sensor'
14
- require 'tcell_agent/policies/appsensor/user_agent_sensor'
15
- require 'tcell_agent/policies/appsensor/xss_sensor'
16
- require 'tcell_agent/utils/params'
3
+ require 'tcell_agent/rust/models'
4
+ require 'tcell_agent/rust/whisperer'
5
+ require 'tcell_agent/policies/policy'
17
6
 
18
7
 
19
8
  module TCellAgent
20
9
  module Policies
21
10
 
22
- class AppSensorPolicy
23
- DETECTION_POINTS_V1 = [
24
- "req_res_size",
25
- "resp_codes",
26
- "ua",
27
- "errors",
28
- "database"]
11
+ class AppSensorPolicy < Policy
12
+ attr_reader :appfirewall_enabled, :appfirewall_ptr
29
13
 
30
- DETECTION_POINTS_V2 = {
31
- "req_size" => RequestSizeSensor,
32
- "resp_size" => ResponseSizeSensor,
33
- "resp_codes" => ResponseCodesSensor,
34
- "xss" => XssSensor,
35
- "sqli" => SqliSensor,
36
- "cmdi" => CmdiSensor,
37
- "fpt" => FptSensor,
38
- "nullbyte" => NullbyteSensor,
39
- "retr" => RetrSensor,
40
- "ua" => UserAgentSensor,
41
- "errors" => MiscSensor,
42
- "database" => DatabaseSensor
43
- }
44
-
45
- DETECTION_POINTS_V2_NON_INJECTION = {
46
- "req_size" => RequestSizeSensor,
47
- "resp_size" => ResponseSizeSensor,
48
- "resp_codes" => ResponseCodesSensor,
49
- "ua" => UserAgentSensor,
50
- "errors" => MiscSensor,
51
- "database" => DatabaseSensor
52
- }
53
-
54
- attr_accessor :policy_id, :options, :enabled, :injections_reporter
55
-
56
- def initialize
57
- @policy_id = nil
58
- @options = Hash.new
59
- @enabled = false
60
- @injections_reporter =
61
- TCellAgent::AppSensor::InjectionsReporter.from_json(0, {}, PayloadsPolicy.new)
14
+ def initialize(appfirewall_enabled=false, appfirewall_ptr=nil)
15
+ @appfirewall_ptr = appfirewall_ptr
16
+ @appfirewall_enabled = appfirewall_enabled
62
17
  end
63
18
 
64
19
  def process_meta_event(appsensor_meta)
65
- return unless @enabled
66
-
67
- check_user_agent(appsensor_meta)
68
- check_request_size(appsensor_meta)
69
- check_response_size(appsensor_meta)
70
- check_response_code(appsensor_meta)
71
-
72
- @injections_reporter.check(appsensor_meta)
73
- end
74
-
75
- def process_db_rows(tcell_data, number_of_records)
76
- return unless @enabled
77
-
78
- TCellAgent::Instrumentation.safe_block("AppSensor Testing Number of DB Rows") do
79
- if self.options.has_key?("database")
80
- self.options["database"].check(tcell_data, number_of_records)
81
- end
82
- end
83
- end
84
-
85
- def check_user_agent(appsensor_meta)
86
- TCellAgent::Instrumentation.safe_block("AppSensor Checking User Agent") do
87
- if self.options.has_key?("ua")
88
- self.options["ua"].check(appsensor_meta)
89
- end
90
- end
91
- end
92
-
93
- def check_request_size(appsensor_meta)
94
- TCellAgent::Instrumentation.safe_block("AppSensor Testing Response Size") do
95
- if self.options.has_key?("req_size")
96
- self.options["req_size"].check(appsensor_meta)
97
- end
98
- end
99
- end
100
-
101
- def check_response_size(appsensor_meta)
102
- return unless @enabled
103
-
104
- TCellAgent::Instrumentation.safe_block("AppSensor Testing Response Size") do
105
- if self.options.has_key?("resp_size")
106
- self.options["resp_size"].check(appsensor_meta)
107
- end
108
- end
109
- end
110
-
111
- def check_response_code(appsensor_meta)
112
- TCellAgent::Instrumentation.safe_block("AppSensor Testing Response Code") do
113
- if self.options.has_key?("resp_codes")
114
- self.options["resp_codes"].check(appsensor_meta, appsensor_meta.response_code)
115
- end
116
- end
117
- end
20
+ return unless @appfirewall_enabled && @appfirewall_ptr
118
21
 
119
- def csrf_rejected(tcell_data, exception_class)
120
- TCellAgent::Instrumentation.safe_block("AppSensor CSRF Exception processing") do
121
- if self.options.has_key?("errors")
122
- self.options["errors"].csrf_rejected(tcell_data, exception_class)
123
- end
22
+ TCellAgent::Instrumentation.safe_block("AppSensor inspection") do
23
+ request_response = TCellAgent::Rust::Models.create_request_response(appsensor_meta)
24
+ whisper = TCellAgent::Rust::Whisperer.apply_appfirewall(@appfirewall_ptr, request_response)
25
+ TCellAgent::AppSensor::InjectionsReporter.report_and_log(whisper["apply_response"])
124
26
  end
125
27
  end
126
28
 
127
- def sql_exception_detected(tcell_data, exception)
128
- TCellAgent::Instrumentation.safe_block("AppSensor SQL Exception processing") do
129
- if self.options.has_key?("errors")
130
- self.options["errors"].sql_exception_detected(tcell_data, exception)
131
- end
132
- end
29
+ def free_native_memory
30
+ TCellAgent::Rust::Whisperer.free_appfirewall(@appfirewall_ptr) if @appfirewall_ptr
133
31
  end
134
32
 
135
33
  def self.from_json(policy_json)
136
34
  return nil unless policy_json
137
- policy_json = policy_json.deep_dup
138
35
 
139
- sensor_policy = AppSensorPolicy.new
140
- if policy_json.has_key?("policy_id")
141
- sensor_policy.policy_id = policy_json["policy_id"]
36
+ whisper = TCellAgent::Rust::Whisperer.init_appfirewall(
37
+ policy_json, TCellAgent.configuration.allow_payloads
38
+ )
39
+ if whisper["error"]
40
+ TCellAgent.logger.debug("Error initializing AppFirewall Policy: #{whisper['error']}")
41
+ return AppSensorPolicy.new
142
42
  else
143
- raise "Policy ID missing"
144
- end
145
-
146
- if policy_json.has_key?("data")
147
- data_json = policy_json["data"]
148
-
149
- if policy_json["version"] && policy_json["version"] == 2
150
- if data_json
151
- sensors_json = data_json.fetch("sensors", {})
152
-
153
- if sensors_json.empty?
154
- sensor_policy.enabled = false
155
-
156
- else
157
- sensor_policy.enabled = true
158
-
159
- options_hash = data_json.fetch("options", {})
160
- collect_full_uri = options_hash.fetch("uri_options", {}).fetch("collect_full_uri", false)
161
-
162
- DETECTION_POINTS_V2_NON_INJECTION.each do |sensor_name, sensor_class|
163
- settings = sensors_json.fetch(sensor_name, {})
164
- updated_settings = {
165
- "enabled" => sensors_json.has_key?(sensor_name),
166
- "collect_full_uri" => collect_full_uri
167
- }.merge(settings)
168
-
169
- sensor_policy.options[sensor_name] =
170
- sensor_class.new(updated_settings)
171
- end
172
-
173
- payloads_policy = PayloadsPolicy.from_json(options_hash)
174
- sensor_policy.injections_reporter =
175
- TCellAgent::AppSensor::InjectionsReporter.from_json(
176
- 2, sensors_json, payloads_policy, collect_full_uri)
177
- end
178
- end
179
-
180
- else
181
- if data_json
182
- options_json = data_json.fetch("options", {})
183
-
184
- if options_json.empty?
185
- sensor_policy.enabled = false
186
-
187
- else
188
- sensor_policy.enabled = true
189
-
190
- payloads_policy = PayloadsPolicy.from_json({
191
- "payloads" => {
192
- "send_payloads" => true,
193
- "log_payloads" => true
194
- }
195
- })
196
-
197
- sensor_policy.injections_reporter =
198
- TCellAgent::AppSensor::InjectionsReporter.from_json(1, data_json, payloads_policy)
199
-
200
- enabled = options_json.fetch("req_res_size", false)
201
- sensor_policy.options["req_size"] = RequestSizeSensor.new({"enabled" => enabled})
202
- sensor_policy.options["resp_size"] = ResponseSizeSensor.new({"enabled" => enabled})
203
-
204
- enabled = options_json.fetch("resp_codes", false)
205
- sensor_policy.options["resp_codes"] = ResponseCodesSensor.new({
206
- "enabled" => enabled,
207
- "series_400_enabled" => true,
208
- "series_500_enabled" => true})
209
-
210
- sensor_policy.options["ua"] = UserAgentSensor.new({
211
- "enabled" => false, "empty_enabled" => false
212
- })
213
-
214
- sensor_policy.options["errors"] = MiscSensor.new({
215
- "enabled" => false,
216
- "csrf_exception_enabled" => false,
217
- "sql_exception_enabled" => false
218
- })
219
-
220
- sensor_policy.options["database"] = DatabaseSensor.new({
221
- "enabled" => false
222
- })
223
- end
224
- end
225
- end
43
+ return AppSensorPolicy.new(whisper["enabled"], whisper["policy_ptr"])
226
44
  end
227
-
228
- return sensor_policy
229
45
  end
230
46
  end
231
47
 
@@ -2,10 +2,11 @@
2
2
  # See the file "LICENSE" for the full license governing this code.
3
3
 
4
4
  require 'uri'
5
+ require 'tcell_agent/policies/policy'
5
6
 
6
7
  module TCellAgent
7
8
  module Policies
8
- class ClickjackingPolicy
9
+ class ClickjackingPolicy < Policy
9
10
  class ContentSecurityPolicyHeader
10
11
  @@approved_headers = [
11
12
  "csp"
@@ -71,8 +72,9 @@ module TCellAgent
71
72
  end
72
73
  result.each(&block)
73
74
  end
75
+
74
76
  def self.from_json(policy_json)
75
- if (!policy_json)
77
+ if (!policy_json)
76
78
  return nil
77
79
  end
78
80
  csp = ClickjackingPolicy.new
@@ -0,0 +1,196 @@
1
+ require 'tcell_agent/rust/whisperer'
2
+ require 'tcell_agent/sensor_events/command_injection'
3
+ require 'tcell_agent/policies/policy'
4
+
5
+
6
+ module TCellAgent
7
+ module Policies
8
+
9
+ class CommandRule
10
+ IGNORE = "ignore"
11
+ REPORT = "report"
12
+ BLOCK = "block"
13
+
14
+ attr_reader :rule_id, :action, :command
15
+
16
+ def initialize(policy_json)
17
+ @rule_id = nil
18
+ @action = nil
19
+ @command = nil
20
+
21
+ if policy_json
22
+ @rule_id = policy_json["rule_id"]
23
+ @action = policy_json["action"]
24
+ @command = policy_json["command"]
25
+ end
26
+ end
27
+
28
+ def ignore?
29
+ @action == IGNORE
30
+ end
31
+
32
+ def report?
33
+ @action == REPORT
34
+ end
35
+
36
+ def block?
37
+ @action == BLOCK
38
+ end
39
+
40
+ def valid?
41
+ !!@rule_id && [IGNORE, REPORT, BLOCK].include?(@action)
42
+ end
43
+ end
44
+
45
+ class CommandInjectionPolicy < Policy
46
+ attr_accessor :policy_id, :version, :enabled, :overall_action, :command_rules, :compound_statement_rule,
47
+ :collect_full_commandline
48
+
49
+ def initialize
50
+ @enabled = false
51
+ @version = nil
52
+ @policy_id = nil
53
+ @overall_action = nil
54
+ @command_rules = {}
55
+ @compound_statement_rule = nil
56
+ @collect_full_commandline = false
57
+ end
58
+
59
+ def self.from_json(policy_json)
60
+ return nil unless policy_json
61
+ policy_json = policy_json.deep_dup
62
+
63
+ policy_id = policy_json["policy_id"]
64
+
65
+ raise "Policy ID missing" unless policy_id
66
+
67
+ command_injection_policy = CommandInjectionPolicy.new
68
+ command_injection_policy.policy_id = policy_id
69
+ command_injection_policy.version = policy_json["version"]
70
+
71
+ if 1 != command_injection_policy.version
72
+ TCellAgent.logger.error("Command Injection not supported: #{command_injection_policy.version}")
73
+ return command_injection_policy
74
+ end
75
+
76
+ policy_data = policy_json["data"]
77
+ command_rules = {}
78
+ overall_action = nil
79
+ compound_statement_rule = nil
80
+ if policy_data
81
+ command_injection_policy.collect_full_commandline = !!policy_data["collect_full_commandline"]
82
+
83
+ (policy_data["command_rules"] or []).each do |command_rule_policy|
84
+ command_rule = CommandRule.new(command_rule_policy)
85
+ if command_rule.valid?
86
+ command = command_rule.command
87
+ if command
88
+ if command_rules.has_key?(command)
89
+ TCellAgent.logger.warn(
90
+ "CommandInjectionPolicy multiple rules for one " +
91
+ "command (dropping rule): #{command} #{command_rule.action}"
92
+ )
93
+ else
94
+ command_rules[command] = command_rule
95
+ end
96
+ elsif !command_rule.ignore?
97
+ overall_action = command_rule
98
+ end
99
+ end
100
+ end
101
+
102
+ compound_statement_rules = policy_data["compound_statement_rules"]
103
+ if compound_statement_rules && compound_statement_rules.size > 0
104
+ compound_statement_rule = CommandRule.new(compound_statement_rules[0])
105
+ if !compound_statement_rule.valid? || compound_statement_rule.ignore?
106
+ compound_statement_rule = nil
107
+ end
108
+ end
109
+
110
+ command_injection_policy.command_rules = command_rules
111
+ command_injection_policy.overall_action = overall_action
112
+ command_injection_policy.compound_statement_rule = compound_statement_rule
113
+ command_injection_policy.enabled = !overall_action.nil? || !compound_statement_rule.nil? || command_rules.size > 0
114
+ end
115
+
116
+ command_injection_policy
117
+ end
118
+
119
+ def block?(cmd, tcell_context)
120
+ return false unless @enabled
121
+
122
+ commands = parse_cmd(cmd).fetch('commands', [])
123
+
124
+ command_injection_match_events = []
125
+ block_command = false
126
+
127
+ if commands.size > 1 && !!@compound_statement_rule
128
+ if !@compound_statement_rule.ignore?
129
+ command_injection_match_events.push(
130
+ TCellAgent::SensorEvents::CommandInjectionMatchEvent.new(
131
+ @compound_statement_rule.rule_id, @compound_statement_rule.command
132
+ )
133
+ )
134
+ block_command = block_command || @compound_statement_rule.block?
135
+ end
136
+ end
137
+
138
+ commands.each do |command_info|
139
+ command = command_info["command"]
140
+ command_rule = command_rules[command] || @overall_action
141
+ if command_rule && !command_rule.ignore?
142
+ command_injection_match_events.push(
143
+ TCellAgent::SensorEvents::CommandInjectionMatchEvent.new(
144
+ command_rule.rule_id,
145
+ command
146
+ )
147
+ )
148
+ block_command = block_command || command_rule.block?
149
+ end
150
+ end
151
+
152
+ if command_injection_match_events.size > 0
153
+ method, remote_address, route_id, session_id, user_id, full_commandline = nil
154
+ if tcell_context
155
+ method = tcell_context.request_method
156
+ remote_address = tcell_context.ip_address
157
+ route_id = tcell_context.route_id
158
+ session_id = tcell_context.hmac_session_id
159
+ user_id = tcell_context.user_id
160
+ end
161
+
162
+ if @collect_full_commandline
163
+ full_commandline = cmd
164
+ end
165
+
166
+ TCellAgent.send_event(
167
+ TCellAgent::SensorEvents::CommandInjectionEvent.new(
168
+ commands,
169
+ block_command,
170
+ command_injection_match_events,
171
+ method=method,
172
+ remote_address=remote_address,
173
+ route_id=route_id,
174
+ session_id=session_id,
175
+ user_id=user_id,
176
+ full_commandline=full_commandline
177
+ )
178
+ )
179
+ end
180
+
181
+ block_command
182
+ end
183
+
184
+ private
185
+ def parse_cmd(cmd)
186
+ TCellAgent::Instrumentation.safe_block("Call Rust Parse Command") do
187
+ require "tcell_agent/rust/whisperer"
188
+
189
+ return TCellAgent::Rust::Whisperer.parse_cmd(cmd)
190
+ end
191
+
192
+ return {}
193
+ end
194
+ end
195
+ end
196
+ end
@@ -2,13 +2,14 @@
2
2
  # See the file "LICENSE" for the full license governing this code.
3
3
 
4
4
  require 'uri'
5
- require 'tcell_agent/sensor_events/util/sanitizer_utilities'
6
5
  require 'tcell_agent/configuration'
6
+ require 'tcell_agent/policies/policy'
7
+ require 'tcell_agent/sensor_events/util/sanitizer_utilities'
7
8
 
8
9
  module TCellAgent
9
10
  module Policies
10
11
 
11
- class ContentSecurityPolicy
12
+ class ContentSecurityPolicy < Policy
12
13
  class ContentSecurityPolicyHeader
13
14
  @@approved_headers = [
14
15
  "csp",
@@ -1,8 +1,10 @@
1
1
  require 'set'
2
+ require 'tcell_agent/policies/policy'
3
+
2
4
 
3
5
  module TCellAgent
4
6
  module Policies
5
- class DataLossPolicy
7
+ class DataLossPolicy < Policy
6
8
  class FilterActions
7
9
  attr_accessor :body_event
8
10
  attr_accessor :body_redact
@@ -10,10 +10,12 @@
10
10
  #+"}";
11
11
  require 'pbkdf2'
12
12
  require 'openssl'
13
+ require 'tcell_agent/policies/policy'
14
+
13
15
 
14
16
  module TCellAgent
15
17
  module Policies
16
- class HoneytokensPolicy
18
+ class HoneytokensPolicy < Policy
17
19
  attr_accessor :policy_id
18
20
  attr_accessor :token_salt
19
21
  attr_accessor :cred_tokens
@@ -1,58 +1,59 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
  require 'uri'
3
- require 'tcell_agent/logger'
4
- require 'tcell_agent/sensor_events/util/redirect_utils'
5
- # See the file "LICENSE" for the full license governing this code.
6
3
 
7
- #{}"http-tx": {
8
- # "policy_id":"afh023",
9
- # "types": {
10
- # "firehose": { enabled: true },
11
- #{}"auth_framework_only": {enabled: true},
12
- #{}"{}structure": {enabled: true },
13
- #{}"fingerprint": {enabled: true }
14
- #}
15
- #},
4
+ require 'tcell_agent/policies/policy'
5
+ require 'tcell_agent/logger'
16
6
 
17
7
  module TCellAgent
18
8
  module Policies
19
- class HttpRedirectPolicy
20
- attr_accessor :policy_id
21
- attr_accessor :enabled
22
- attr_accessor :whitelist
23
- attr_accessor :block
9
+
10
+ class HttpRedirectPolicy < Policy
11
+ attr_accessor :policy_id, :enabled, :whitelist, :block, :data_scheme_allowed
12
+
24
13
  def initialize
25
14
  @policy_id = nil
26
15
  @enabled = false
27
16
  @whitelist = []
28
17
  @block = false
18
+ @data_scheme_allowed = false
29
19
  end
30
- def check(host, current_host)
20
+
21
+ def suspicious_redirect?(host, current_host)
31
22
  if (!(host) || host == "" || host == current_host)
32
23
  # local redirect
33
24
  return false
34
25
  end
35
- if (whitelist)
36
- whitelist.each do |domain|
37
- if (TCellAgent::SensorEvents::Util.wildcardMatch(host, domain))
38
- return false
39
- end
26
+
27
+ whitelist.each do |whitelist_regex|
28
+ if (host =~ whitelist_regex) || ("www.#{host}" =~ whitelist_regex)
29
+ return false
40
30
  end
41
31
  end
42
- return true
32
+
33
+ true
43
34
  end
44
- def enforce(target_url, current_host, current_path, method, route_id, status_code, remote_addr, hmac_session_id=nil)
45
- if @enabled == false
46
- return nil
47
- end
48
- uri = URI.parse(target_url)
49
- host = uri.host
50
- if self.check(host, current_host) == false
51
- return nil
35
+
36
+ def enforce(target_uri, request_uri, current_path, method, route_id, status_code, remote_addr, hmac_session_id=nil)
37
+ return nil unless @enabled
38
+
39
+ current_host = URI.parse(request_uri).host
40
+ if target_uri.downcase.start_with?("data:")
41
+ if @data_scheme_allowed
42
+ return nil
43
+ end
44
+
45
+ target_host = target_uri.split(",")[0]
46
+
47
+ else
48
+ target_host = URI.parse(target_uri).host
49
+ if !self.suspicious_redirect?(target_host, current_host)
50
+ return nil
51
+ end
52
52
  end
53
+
53
54
  begin
54
55
  event = TCellAgent::SensorEvents::TCellRedirectSensorEvent.new(
55
- host,
56
+ target_host,
56
57
  current_host,
57
58
  current_path,
58
59
  method,
@@ -66,29 +67,42 @@ module TCellAgent
66
67
  rescue Exception => ie
67
68
  TCellAgent.logger.error("uncaught exception while creating redirect event: #{ie.message}")
68
69
  end
69
- if @block == true
70
+
71
+ if @block
70
72
  return "/"
73
+ else
74
+ return nil
71
75
  end
72
- return nil
73
76
  end
77
+
74
78
  def self.from_json(policy_json)
75
- if (!policy_json)
79
+ if (!policy_json)
76
80
  return nil
77
81
  end
82
+
78
83
  http_redirect_policy = HttpRedirectPolicy.new
79
84
  if policy_json.has_key?("policy_id")
80
85
  http_redirect_policy.policy_id = policy_json["policy_id"]
81
86
  else
82
87
  raise "Policy ID missing"
83
88
  end
89
+
84
90
  if policy_json.has_key?("data")
85
91
  policy_data_json = policy_json["data"]
86
92
  http_redirect_policy.enabled = policy_data_json.fetch("enabled", false)
87
- http_redirect_policy.whitelist = policy_data_json.fetch("whitelist", [])
88
93
  http_redirect_policy.block = policy_data_json.fetch("block", false)
94
+ http_redirect_policy.data_scheme_allowed = policy_data_json.fetch("dataSchemeAllowed", false)
95
+
96
+ http_redirect_policy.whitelist = []
97
+ policy_data_json.fetch("whitelist", []).each do |regex_pattern|
98
+ escaped = Regexp.escape(regex_pattern).gsub('\*','.*?')
99
+ http_redirect_policy.whitelist.push(Regexp.new("^#{escaped}$", Regexp::IGNORECASE))
100
+ end
89
101
  end
102
+
90
103
  return http_redirect_policy
91
104
  end
92
105
  end
106
+
93
107
  end
94
108
  end
@@ -8,9 +8,12 @@
8
8
  #}
9
9
  #},
10
10
 
11
+ require 'tcell_agent/policies/policy'
12
+
13
+
11
14
  module TCellAgent
12
15
  module Policies
13
- class HttpTxPolicy
16
+ class HttpTxPolicy < Policy
14
17
  attr_accessor :policy_id
15
18
  attr_accessor :firehose
16
19
  attr_accessor :auth_framework
@@ -23,6 +26,7 @@ module TCellAgent
23
26
  @profile = {"enabled"=>false }
24
27
  @fingerprint = {"enabled"=>false, "hmacUserAgent"=>false, "hmacUserId"=>false, "sampling"=>nil }
25
28
  end
29
+
26
30
  def self.from_json(policy_json)
27
31
  if (!policy_json)
28
32
  return nil