tcell_agent 0.2.12 → 0.2.13

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/lib/tcell_agent.rb +2 -2
  3. data/lib/tcell_agent/agent/policy_manager.rb +1 -1
  4. data/lib/tcell_agent/api.rb +2 -2
  5. data/lib/tcell_agent/appsensor/rules/appsensor_rule_manager.rb +46 -0
  6. data/lib/tcell_agent/appsensor/rules/appsensor_rule_set.rb +67 -0
  7. data/lib/tcell_agent/appsensor/rules/baserules.json +153 -0
  8. data/lib/tcell_agent/configuration.rb +7 -1
  9. data/lib/tcell_agent/instrumentation.rb +3 -0
  10. data/lib/tcell_agent/logger.rb +25 -3
  11. data/lib/tcell_agent/policies/appsensor/cmdi_sensor.rb +19 -0
  12. data/lib/tcell_agent/policies/appsensor/fpt_sensor.rb +19 -0
  13. data/lib/tcell_agent/policies/appsensor/injection_sensor.rb +136 -0
  14. data/lib/tcell_agent/policies/appsensor/login_sensor.rb +42 -0
  15. data/lib/tcell_agent/policies/appsensor/nullbyte_sensor.rb +22 -0
  16. data/lib/tcell_agent/policies/appsensor/request_size_sensor.rb +21 -0
  17. data/lib/tcell_agent/policies/appsensor/response_codes_sensor.rb +58 -0
  18. data/lib/tcell_agent/policies/appsensor/response_size_sensor.rb +21 -0
  19. data/lib/tcell_agent/policies/appsensor/retr_sensor.rb +18 -0
  20. data/lib/tcell_agent/policies/appsensor/sensor.rb +28 -0
  21. data/lib/tcell_agent/policies/appsensor/size_sensor.rb +43 -0
  22. data/lib/tcell_agent/policies/appsensor/sqli_sensor.rb +25 -0
  23. data/lib/tcell_agent/policies/appsensor/xss_sensor.rb +26 -0
  24. data/lib/tcell_agent/policies/appsensor_policy.rb +198 -67
  25. data/lib/tcell_agent/policies/clickjacking_policy.rb +1 -1
  26. data/lib/tcell_agent/policies/content_security_policy.rb +1 -1
  27. data/lib/tcell_agent/policies/dataloss_policy.rb +1 -1
  28. data/lib/tcell_agent/policies/honeytokens_policy.rb +1 -1
  29. data/lib/tcell_agent/policies/http_redirect_policy.rb +1 -1
  30. data/lib/tcell_agent/policies/http_tx_policy.rb +1 -1
  31. data/lib/tcell_agent/policies/login_fraud_policy.rb +1 -1
  32. data/lib/tcell_agent/policies/secure_headers_policy.rb +1 -1
  33. data/lib/tcell_agent/rails.rb +0 -1
  34. data/lib/tcell_agent/rails/auth/devise.rb +0 -1
  35. data/lib/tcell_agent/rails/dlp.rb +58 -13
  36. data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +0 -1
  37. data/lib/tcell_agent/rails/middleware/context_middleware.rb +0 -1
  38. data/lib/tcell_agent/rails/middleware/global_middleware.rb +0 -1
  39. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +6 -34
  40. data/lib/tcell_agent/sensor_events/appsensor_event.rb +59 -0
  41. data/lib/tcell_agent/sensor_events/appsensor_meta_event.rb +95 -0
  42. data/lib/tcell_agent/servers/rails_server.rb +18 -9
  43. data/lib/tcell_agent/utils/params.rb +40 -0
  44. data/lib/tcell_agent/version.rb +1 -1
  45. data/spec/lib/tcell_agent/appsensor/rules/appsensor_rule_manager_spec.rb +39 -0
  46. data/spec/lib/tcell_agent/appsensor/rules/appsensor_rule_set_spec.rb +152 -0
  47. data/spec/lib/tcell_agent/instrumentation_spec.rb +4 -4
  48. data/spec/lib/tcell_agent/policies/appsensor/cmdi_sensor_spec.rb +128 -0
  49. data/spec/lib/tcell_agent/policies/appsensor/fpt_sensor_spec.rb +128 -0
  50. data/spec/lib/tcell_agent/policies/appsensor/login_sensor_spec.rb +104 -0
  51. data/spec/lib/tcell_agent/policies/appsensor/nullbyte_sensor_spec.rb +132 -0
  52. data/spec/lib/tcell_agent/policies/appsensor/request_size_sensor_spec.rb +164 -0
  53. data/spec/lib/tcell_agent/policies/appsensor/response_codes_sensor_spec.rb +194 -0
  54. data/spec/lib/tcell_agent/policies/appsensor/response_size_sensor_spec.rb +157 -0
  55. data/spec/lib/tcell_agent/policies/appsensor/retr_sensor_spec.rb +128 -0
  56. data/spec/lib/tcell_agent/policies/appsensor/sqli_sensor_spec.rb +151 -0
  57. data/spec/lib/tcell_agent/policies/appsensor/xss_sensor_spec.rb +652 -0
  58. data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +461 -28
  59. data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +4 -4
  60. data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +6 -6
  61. data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +10 -10
  62. data/spec/lib/tcell_agent/policies/honeytokens_policy_spec.rb +1 -1
  63. data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +1 -1
  64. data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +1 -1
  65. data/spec/lib/tcell_agent/policies/login_policy_spec.rb +2 -2
  66. data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +4 -4
  67. data/spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb +67 -7
  68. data/spec/lib/tcell_agent/sensor_events/appsensor_meta_event_spec.rb +80 -0
  69. data/spec/lib/tcell_agent/utils/params_spec.rb +119 -0
  70. data/spec/support/resources/baserules.json +155 -0
  71. metadata +51 -12
  72. data/lib/tcell_agent/appsensor.rb +0 -42
  73. data/lib/tcell_agent/appsensor/cmdi.rb +0 -32
  74. data/lib/tcell_agent/appsensor/path_traversal.rb +0 -33
  75. data/lib/tcell_agent/appsensor/sqli.rb +0 -55
  76. data/lib/tcell_agent/appsensor/xss.rb +0 -40
  77. data/lib/tcell_agent/sensor_events/app_sensor.rb +0 -302
  78. data/spec/lib/tcell_agent/appsensor_spec.rb +0 -65
  79. data/spec/lib/tcell_agent/sensor_events/tcell_app_sensor_event_processor_spec.rb +0 -289
@@ -0,0 +1,136 @@
1
+ require 'tcell_agent/policies/appsensor/sensor'
2
+ require 'tcell_agent/utils/params'
3
+
4
+
5
+ module TCellAgent
6
+ module Policies
7
+ class InjectionSensor < Sensor
8
+ include TCellAgent::Utils::Params
9
+
10
+ attr_accessor :enabled, :detection_point, :exclude_headers, :exclude_forms,
11
+ :exclude_cookies, :exclusions, :active_pattern_ids, :v1_compatability_enabled,
12
+ :rule_manager
13
+
14
+
15
+ def initialize(detection_point, policy_json=nil)
16
+ @enabled = false
17
+ @detection_point = detection_point
18
+ @exclude_headers = false
19
+ @exclude_forms = false
20
+ @exclude_cookies = false
21
+ @exclusions = {}
22
+ @active_pattern_ids = {}
23
+ @v1_compatability_enabled = false
24
+ @rule_manager = AppSensorRuleManager.new
25
+
26
+ if policy_json
27
+ @enabled = policy_json.fetch("enabled", false)
28
+ @exclude_headers = policy_json.fetch("exclude_headers", false)
29
+ @exclude_forms = policy_json.fetch("exclude_forms", false)
30
+ @exclude_cookies = policy_json.fetch("exclude_cookies", false)
31
+ @v1_compatability_enabled = policy_json.fetch("v1_compatability_enabled", false)
32
+ @rule_manager = policy_json.fetch("rule_manager", AppSensorRuleManager.new)
33
+
34
+ policy_json.fetch("patterns", []).each do |pattern|
35
+ @active_pattern_ids[pattern] = true
36
+ end
37
+
38
+ policy_json.fetch("exclusions", {}).each do |common_word, locations|
39
+ @exclusions[common_word] = locations
40
+ end
41
+ end
42
+ end
43
+
44
+ def get_ruleset
45
+ @rule_manager.get_ruleset_for(@detection_point)
46
+ end
47
+
48
+ def find_vulnerability(param_name, param_value)
49
+ rules = get_ruleset
50
+ return nil unless rules
51
+
52
+ param_deep_loop(param_name, param_value) do |name, value|
53
+ rules.check_violation(name, value, @active_pattern_ids, @v1_compatability_enabled)
54
+ end
55
+ end
56
+
57
+ def check(type_of_param, appsensor_meta, param_name, param_value)
58
+ return false unless @enabled
59
+
60
+ if @exclude_forms && (GET_PARAM == type_of_param or POST_PARAM == type_of_param or JSON_PARAM == type_of_param)
61
+ return false
62
+ end
63
+
64
+ if @exclude_cookies && COOKIE_PARAM == type_of_param
65
+ return false
66
+ end
67
+
68
+ vuln_results = find_vulnerability(param_name, param_value)
69
+
70
+ if vuln_results
71
+ vuln_param = vuln_results["param"]
72
+ payload = nil
73
+
74
+ if TCellAgent.configuration.allow_unencrypted_appsensor_payloads
75
+ payload = vuln_results["value"]
76
+ end
77
+
78
+ if vuln_param
79
+ unless payload.nil?
80
+ if TCellAgent.configuration.blacklisted_params.has_key?(vuln_param.downcase)
81
+ payload = "BLACKLISTED"
82
+
83
+ elsif TCellAgent.configuration.whitelist_present &&
84
+ !TCellAgent.configuration.whitelisted_params.has_key?(vuln_param.downcase)
85
+ payload = "NOT_WHITELISTED"
86
+ end
87
+ end
88
+
89
+ log_appsensor_events(type_of_param, appsensor_meta, vuln_param, vuln_results["value"])
90
+
91
+ send_event(
92
+ appsensor_meta,
93
+ @detection_point,
94
+ vuln_param,
95
+ {"t" => type_of_param}.to_json,
96
+ payload,
97
+ vuln_results["pattern"]
98
+ )
99
+
100
+ return true
101
+ end
102
+ end
103
+
104
+ return false
105
+ end
106
+
107
+ def log_appsensor_events(type_of_param, appsensor_meta, vuln_param, vuln_value)
108
+ if TCellAgent.configuration.log_appfirewall_events
109
+ event = TCellAgent::SensorEvents::TCellAppSensorEvent.new(
110
+ appsensor_meta.location,
111
+ @detection_point,
112
+ appsensor_meta.method,
113
+ appsensor_meta.remote_address,
114
+ vuln_param,
115
+ appsensor_meta.route_id,
116
+ {"t" => type_of_param}.to_json,
117
+ appsensor_meta.transaction_id,
118
+ appsensor_meta.session_id,
119
+ appsensor_meta.user_id,
120
+ vuln_value
121
+ )
122
+ event.post_process
123
+ TCellAgent.appfirewall_payloads_logger.info(event.to_json)
124
+ end
125
+ end
126
+
127
+ def to_s
128
+ "<#{self.class.name} enabled: #{@enabled} dp: #{@detection_point} " +
129
+ "exclude_headers: #{@exclude_headers} exclude_forms: #{exclude_forms} " +
130
+ "exclude_cookies: #{exclude_cookies} v1_compatability_enabled: #{@v1_compatability_enabled} " +
131
+ "active_pattern_ids: #{@active_pattern_ids} exclusions: #{exclusions}>"
132
+ end
133
+ end
134
+
135
+ end
136
+ end
@@ -0,0 +1,42 @@
1
+ require 'tcell_agent/policies/appsensor/size_sensor'
2
+ require 'tcell_agent/sensor_events/util/utils'
3
+
4
+
5
+ module TCellAgent
6
+ module Policies
7
+
8
+ class LoginSensor < Sensor
9
+ LOGIN_FAILURE_DP = "lgnFlr"
10
+
11
+ attr_accessor :enabled
12
+
13
+ def initialize(policy_json=nil)
14
+ @enabled = false
15
+
16
+ if policy_json
17
+ @enabled = policy_json.fetch("enabled", false)
18
+ end
19
+ end
20
+
21
+
22
+ def check(appsensor_meta, username)
23
+ return unless self.enabled
24
+
25
+ if username
26
+ username = TCellAgent::SensorEvents::Util.hmac(
27
+ username,
28
+ TCellAgent::SensorEvents::Util.getHmacKey()
29
+ )
30
+ end
31
+
32
+ send_event(appsensor_meta, LOGIN_FAILURE_DP, username, nil)
33
+ end
34
+
35
+ def to_s
36
+ "<#{self.class.name} enabled: #{@enabled}>"
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ require 'tcell_agent/policies/appsensor/injection_sensor'
2
+
3
+ module TCellAgent
4
+ module Policies
5
+
6
+ class NullbyteSensor < InjectionSensor
7
+
8
+ def initialize(policy_json=nil)
9
+ super(
10
+ "null",
11
+ policy_json
12
+ )
13
+ end
14
+
15
+ def get_ruleset
16
+ @rule_manager.get_ruleset_for("nullbyte")
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ require 'tcell_agent/policies/appsensor/size_sensor'
2
+
3
+
4
+ module TCellAgent
5
+ module Policies
6
+
7
+ class RequestSizeSensor < SizeSensor
8
+ MAX_NORMAL_REQUEST_BYTES = 1024*512
9
+ DP_UNUSUAL_REQUEST_SIZE = "reqsz"
10
+
11
+ def initialize(policy_json=nil)
12
+ super(
13
+ MAX_NORMAL_REQUEST_BYTES,
14
+ DP_UNUSUAL_REQUEST_SIZE,
15
+ policy_json
16
+ )
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,58 @@
1
+ require 'tcell_agent/policies/appsensor/sensor'
2
+
3
+
4
+ module TCellAgent
5
+ module Policies
6
+
7
+ class ResponseCodesSensor < Sensor
8
+
9
+ RESPONSE_CODE_DP_DICT = {
10
+ 401 => "s401",
11
+ 403 => "s403",
12
+ 404 => "s404",
13
+ 4 => "s4xx",
14
+ 500 => "s500",
15
+ 5 => "s5xx"
16
+ }
17
+
18
+ attr_accessor :enabled, :series_400_enabled, :series_500_enabled
19
+
20
+ def initialize(policy_json=nil)
21
+ @enabled = false
22
+ @series_400_enabled = false
23
+ @series_500_enabled = false
24
+
25
+ if policy_json
26
+ @enabled = policy_json.fetch("enabled", false)
27
+ @series_400_enabled = policy_json.fetch("series_400_enabled", false)
28
+ @series_500_enabled = policy_json.fetch("series_500_enabled", false)
29
+ end
30
+ end
31
+
32
+ def check(appsensor_meta, response_code)
33
+ return unless self.enabled
34
+
35
+ return if response_code == 200
36
+ return if !self.series_400_enabled && (response_code >= 400 && response_code < 500)
37
+ return if !self.series_500_enabled and (response_code >= 500 && response_code < 600)
38
+
39
+ dp = RESPONSE_CODE_DP_DICT.fetch(response_code, nil)
40
+
41
+ if dp.nil?
42
+ code_series = (response_code / 100).to_i
43
+ dp = RESPONSE_CODE_DP_DICT.fetch(code_series, nil)
44
+ end
45
+
46
+ if dp
47
+ send_event(appsensor_meta, dp, response_code.to_s, nil)
48
+ end
49
+
50
+ def to_s
51
+ "<#{self.class.name} enabled: #{@enabled} series_400_enabled: #{@series_400_enabled} series_500_enabled: #{@series_500_enabled}>"
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,21 @@
1
+ require 'tcell_agent/policies/appsensor/size_sensor'
2
+
3
+
4
+ module TCellAgent
5
+ module Policies
6
+
7
+ class ResponseSizeSensor < SizeSensor
8
+ MAX_NORMAL_RESPONSE_BYTES = 1024*1024*2
9
+ DP_UNUSUAL_RESPONSE_SIZE = "rspsz"
10
+
11
+ def initialize(policy_json=nil)
12
+ super(
13
+ MAX_NORMAL_RESPONSE_BYTES,
14
+ DP_UNUSUAL_RESPONSE_SIZE,
15
+ policy_json
16
+ )
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ require 'tcell_agent/policies/appsensor/injection_sensor'
2
+
3
+ module TCellAgent
4
+ module Policies
5
+
6
+ class RetrSensor < InjectionSensor
7
+
8
+ def initialize(policy_json=nil)
9
+ super(
10
+ "retr",
11
+ policy_json
12
+ )
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ require 'tcell_agent/sensor_events/appsensor_event'
2
+
3
+ module TCellAgent
4
+ module Policies
5
+
6
+ class Sensor
7
+ def send_event(appsensor_meta, detection_point, parameter, data, payload=nil, pattern=nil)
8
+ event = TCellAgent::SensorEvents::TCellAppSensorEvent.new(
9
+ appsensor_meta.location,
10
+ detection_point,
11
+ appsensor_meta.method,
12
+ appsensor_meta.remote_address,
13
+ parameter,
14
+ appsensor_meta.route_id,
15
+ data,
16
+ appsensor_meta.transaction_id,
17
+ appsensor_meta.session_id,
18
+ appsensor_meta.user_id,
19
+ payload,
20
+ pattern
21
+ )
22
+
23
+ TCellAgent.send_event(event)
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,43 @@
1
+ require 'tcell_agent/policies/appsensor/sensor'
2
+
3
+ module TCellAgent
4
+ module Policies
5
+
6
+ class SizeSensor < Sensor
7
+
8
+ attr_accessor :enabled, :limit, :exclude_routes, :dp_code
9
+
10
+ def initialize(default_limit, dp_code, policy_json)
11
+ @enabled = false
12
+ @limit = default_limit
13
+ @exclude_routes = {}
14
+ @dp_code = dp_code
15
+
16
+ if policy_json != nil
17
+ @enabled = policy_json.fetch("enabled", false)
18
+ @limit = policy_json.fetch("limit", @limit)
19
+
20
+ policy_json.fetch("exclude_routes", []).each do |route_id|
21
+ @exclude_routes[route_id] = true
22
+ end
23
+ end
24
+ end
25
+
26
+ def check(appsensor_meta, content_length)
27
+ if !@enabled || @exclude_routes.fetch(appsensor_meta.route_id, false)
28
+ return
29
+ end
30
+
31
+ if content_length && content_length > @limit
32
+ send_event(appsensor_meta, @dp_code, content_length.to_s, nil)
33
+ end
34
+ end
35
+
36
+ def to_s
37
+ "<#{self.class.name} enabled: #{@enabled} limit: #{@limit} dp_code: #{@dp_code} exclude_routes: #{@exclude_routes}>"
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ require 'tcell_agent/policies/appsensor/injection_sensor'
2
+
3
+ module TCellAgent
4
+ module Policies
5
+
6
+ class SqliSensor < InjectionSensor
7
+
8
+ attr_accessor :libinjection
9
+
10
+ def initialize(policy_json=nil)
11
+ super(
12
+ "sqli",
13
+ policy_json
14
+ )
15
+
16
+ @libinjection = false
17
+
18
+ if policy_json
19
+ @libinjection = policy_json.fetch("libinjection", false)
20
+ end
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ require 'tcell_agent/policies/appsensor/injection_sensor'
2
+
3
+
4
+ module TCellAgent
5
+ module Policies
6
+
7
+ class XssSensor < InjectionSensor
8
+
9
+ attr_accessor :libinjection
10
+
11
+ def initialize(policy_json=nil)
12
+ super(
13
+ "xss",
14
+ policy_json
15
+ )
16
+
17
+ @libinjection = false
18
+
19
+ if policy_json
20
+ @libinjection = policy_json.fetch("libinjection", false)
21
+ end
22
+ end
23
+ end
24
+
25
+ end
26
+ end