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.
- checksums.yaml +4 -4
- data/lib/tcell_agent.rb +2 -2
- data/lib/tcell_agent/agent/policy_manager.rb +1 -1
- data/lib/tcell_agent/api.rb +2 -2
- data/lib/tcell_agent/appsensor/rules/appsensor_rule_manager.rb +46 -0
- data/lib/tcell_agent/appsensor/rules/appsensor_rule_set.rb +67 -0
- data/lib/tcell_agent/appsensor/rules/baserules.json +153 -0
- data/lib/tcell_agent/configuration.rb +7 -1
- data/lib/tcell_agent/instrumentation.rb +3 -0
- data/lib/tcell_agent/logger.rb +25 -3
- data/lib/tcell_agent/policies/appsensor/cmdi_sensor.rb +19 -0
- data/lib/tcell_agent/policies/appsensor/fpt_sensor.rb +19 -0
- data/lib/tcell_agent/policies/appsensor/injection_sensor.rb +136 -0
- data/lib/tcell_agent/policies/appsensor/login_sensor.rb +42 -0
- data/lib/tcell_agent/policies/appsensor/nullbyte_sensor.rb +22 -0
- data/lib/tcell_agent/policies/appsensor/request_size_sensor.rb +21 -0
- data/lib/tcell_agent/policies/appsensor/response_codes_sensor.rb +58 -0
- data/lib/tcell_agent/policies/appsensor/response_size_sensor.rb +21 -0
- data/lib/tcell_agent/policies/appsensor/retr_sensor.rb +18 -0
- data/lib/tcell_agent/policies/appsensor/sensor.rb +28 -0
- data/lib/tcell_agent/policies/appsensor/size_sensor.rb +43 -0
- data/lib/tcell_agent/policies/appsensor/sqli_sensor.rb +25 -0
- data/lib/tcell_agent/policies/appsensor/xss_sensor.rb +26 -0
- data/lib/tcell_agent/policies/appsensor_policy.rb +198 -67
- data/lib/tcell_agent/policies/clickjacking_policy.rb +1 -1
- data/lib/tcell_agent/policies/content_security_policy.rb +1 -1
- data/lib/tcell_agent/policies/dataloss_policy.rb +1 -1
- data/lib/tcell_agent/policies/honeytokens_policy.rb +1 -1
- data/lib/tcell_agent/policies/http_redirect_policy.rb +1 -1
- data/lib/tcell_agent/policies/http_tx_policy.rb +1 -1
- data/lib/tcell_agent/policies/login_fraud_policy.rb +1 -1
- data/lib/tcell_agent/policies/secure_headers_policy.rb +1 -1
- data/lib/tcell_agent/rails.rb +0 -1
- data/lib/tcell_agent/rails/auth/devise.rb +0 -1
- data/lib/tcell_agent/rails/dlp.rb +58 -13
- data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +0 -1
- data/lib/tcell_agent/rails/middleware/context_middleware.rb +0 -1
- data/lib/tcell_agent/rails/middleware/global_middleware.rb +0 -1
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +6 -34
- data/lib/tcell_agent/sensor_events/appsensor_event.rb +59 -0
- data/lib/tcell_agent/sensor_events/appsensor_meta_event.rb +95 -0
- data/lib/tcell_agent/servers/rails_server.rb +18 -9
- data/lib/tcell_agent/utils/params.rb +40 -0
- data/lib/tcell_agent/version.rb +1 -1
- data/spec/lib/tcell_agent/appsensor/rules/appsensor_rule_manager_spec.rb +39 -0
- data/spec/lib/tcell_agent/appsensor/rules/appsensor_rule_set_spec.rb +152 -0
- data/spec/lib/tcell_agent/instrumentation_spec.rb +4 -4
- data/spec/lib/tcell_agent/policies/appsensor/cmdi_sensor_spec.rb +128 -0
- data/spec/lib/tcell_agent/policies/appsensor/fpt_sensor_spec.rb +128 -0
- data/spec/lib/tcell_agent/policies/appsensor/login_sensor_spec.rb +104 -0
- data/spec/lib/tcell_agent/policies/appsensor/nullbyte_sensor_spec.rb +132 -0
- data/spec/lib/tcell_agent/policies/appsensor/request_size_sensor_spec.rb +164 -0
- data/spec/lib/tcell_agent/policies/appsensor/response_codes_sensor_spec.rb +194 -0
- data/spec/lib/tcell_agent/policies/appsensor/response_size_sensor_spec.rb +157 -0
- data/spec/lib/tcell_agent/policies/appsensor/retr_sensor_spec.rb +128 -0
- data/spec/lib/tcell_agent/policies/appsensor/sqli_sensor_spec.rb +151 -0
- data/spec/lib/tcell_agent/policies/appsensor/xss_sensor_spec.rb +652 -0
- data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +461 -28
- data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +4 -4
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +6 -6
- data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +10 -10
- data/spec/lib/tcell_agent/policies/honeytokens_policy_spec.rb +1 -1
- data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +1 -1
- data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +1 -1
- data/spec/lib/tcell_agent/policies/login_policy_spec.rb +2 -2
- data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +4 -4
- data/spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb +67 -7
- data/spec/lib/tcell_agent/sensor_events/appsensor_meta_event_spec.rb +80 -0
- data/spec/lib/tcell_agent/utils/params_spec.rb +119 -0
- data/spec/support/resources/baserules.json +155 -0
- metadata +51 -12
- data/lib/tcell_agent/appsensor.rb +0 -42
- data/lib/tcell_agent/appsensor/cmdi.rb +0 -32
- data/lib/tcell_agent/appsensor/path_traversal.rb +0 -33
- data/lib/tcell_agent/appsensor/sqli.rb +0 -55
- data/lib/tcell_agent/appsensor/xss.rb +0 -40
- data/lib/tcell_agent/sensor_events/app_sensor.rb +0 -302
- data/spec/lib/tcell_agent/appsensor_spec.rb +0 -65
- data/spec/lib/tcell_agent/sensor_events/tcell_app_sensor_event_processor_spec.rb +0 -289
|
@@ -5,7 +5,6 @@ require 'uri'
|
|
|
5
5
|
require 'tcell_agent/logger'
|
|
6
6
|
require 'tcell_agent/agent'
|
|
7
7
|
require 'tcell_agent/sensor_events/sensor'
|
|
8
|
-
require 'tcell_agent/sensor_events/app_sensor'
|
|
9
8
|
require 'tcell_agent/sensor_events/server_agent'
|
|
10
9
|
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
|
11
10
|
require 'tcell_agent/sensor_events/util/redirect_utils'
|
|
@@ -5,7 +5,6 @@ require 'uri'
|
|
|
5
5
|
require 'tcell_agent/logger'
|
|
6
6
|
require 'tcell_agent/agent'
|
|
7
7
|
require 'tcell_agent/sensor_events/sensor'
|
|
8
|
-
require 'tcell_agent/sensor_events/app_sensor'
|
|
9
8
|
require 'tcell_agent/sensor_events/server_agent'
|
|
10
9
|
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
|
11
10
|
require 'tcell_agent/sensor_events/util/redirect_utils'
|
|
@@ -5,7 +5,6 @@ require 'uri'
|
|
|
5
5
|
require 'tcell_agent/logger'
|
|
6
6
|
require 'tcell_agent/agent'
|
|
7
7
|
require 'tcell_agent/sensor_events/sensor'
|
|
8
|
-
require 'tcell_agent/sensor_events/app_sensor'
|
|
9
8
|
require 'tcell_agent/sensor_events/server_agent'
|
|
10
9
|
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
|
11
10
|
require 'tcell_agent/sensor_events/util/redirect_utils'
|
|
@@ -5,7 +5,7 @@ require 'uri'
|
|
|
5
5
|
require 'tcell_agent/logger'
|
|
6
6
|
require 'tcell_agent/agent'
|
|
7
7
|
require 'tcell_agent/sensor_events/sensor'
|
|
8
|
-
require 'tcell_agent/sensor_events/
|
|
8
|
+
require 'tcell_agent/sensor_events/appsensor_meta_event'
|
|
9
9
|
require 'tcell_agent/sensor_events/server_agent'
|
|
10
10
|
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
|
11
11
|
require 'tcell_agent/sensor_events/util/redirect_utils'
|
|
@@ -137,45 +137,17 @@ module TCellAgent
|
|
|
137
137
|
def _handle_appsensor(request, response)
|
|
138
138
|
TCellAgent::Instrumentation.safe_block("Handling AppSensor") {
|
|
139
139
|
status_code, response_headers, response_body = response
|
|
140
|
-
appsensor_policy = TCellAgent.policy(TCellAgent::PolicyTypes::AppSensor)
|
|
141
140
|
|
|
142
141
|
if (!(response_body.is_a?(Array)) && !(response_body.is_a?(Rack::BodyProxy)))
|
|
143
142
|
return response
|
|
144
143
|
end
|
|
144
|
+
|
|
145
145
|
rack_response = Rack::Response.new(response)
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
event.response_content_length = (rack_response.length || "0").to_i
|
|
152
|
-
event.request_content_type = request.content_type
|
|
153
|
-
event.remote_addr = request.ip
|
|
154
|
-
event.uri = "#{request.base_url}#{request.fullpath}"
|
|
155
|
-
event.get_params = request.GET
|
|
156
|
-
event.post_params = request.POST
|
|
157
|
-
event.request_body = request.body.gets
|
|
158
|
-
event.cookies = request.cookies
|
|
159
|
-
event.request_method = request.request_method
|
|
160
|
-
|
|
161
|
-
event.request_size = event.request_content_length
|
|
162
|
-
#status, headers, active_response = response
|
|
163
|
-
#if active_response.class != ActionDispatch::Response
|
|
164
|
-
# return response
|
|
165
|
-
#end
|
|
166
|
-
event.status_code = status_code
|
|
167
|
-
event.response_headers = response_headers
|
|
168
|
-
|
|
169
|
-
event.route_id = request.env["tcell.request_data"].route_id
|
|
170
|
-
event.transaction_id = request.env["tcell.request_data"].transaction_id
|
|
171
|
-
event.session_id = request.env["tcell.request_data"].hmac_session_id
|
|
172
|
-
event.user_id = request.env["tcell.request_data"].user_id
|
|
173
|
-
|
|
174
|
-
#puts event.response_headers
|
|
175
|
-
#puts event.cookies, event.post_params, event.get_params, event.uri, event.remote_addr
|
|
176
|
-
#puts event.request_headers
|
|
177
|
-
TCellAgent.send_event(event)
|
|
178
|
-
end
|
|
147
|
+
event = TCellAgent::SensorEvents::AppSensorMetaEvent.build(
|
|
148
|
+
request, rack_response, status_code, response_headers
|
|
149
|
+
)
|
|
150
|
+
TCellAgent.send_event(event)
|
|
179
151
|
}
|
|
180
152
|
response
|
|
181
153
|
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'tcell_agent/sensor_events/sensor'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module TCellAgent
|
|
5
|
+
module SensorEvents
|
|
6
|
+
|
|
7
|
+
class TCellAppSensorEvent < TCellSensorEvent
|
|
8
|
+
|
|
9
|
+
def initialize(location,
|
|
10
|
+
detection_point,
|
|
11
|
+
method,
|
|
12
|
+
remote_addr,
|
|
13
|
+
param,
|
|
14
|
+
route_id,
|
|
15
|
+
data=nil,
|
|
16
|
+
transaction_id=nil,
|
|
17
|
+
session_id=nil,
|
|
18
|
+
user_id=nil,
|
|
19
|
+
payload=nil,
|
|
20
|
+
pattern=nil)
|
|
21
|
+
super("as")
|
|
22
|
+
self["dp"] = detection_point
|
|
23
|
+
self["param"] = param
|
|
24
|
+
self["remote_addr"] = remote_addr
|
|
25
|
+
if (route_id)
|
|
26
|
+
self["rou"] = route_id
|
|
27
|
+
end
|
|
28
|
+
self["m"] = method
|
|
29
|
+
@raw_location = location
|
|
30
|
+
@user_id = user_id
|
|
31
|
+
@transaction_id = transaction_id
|
|
32
|
+
@raw_session_id = session_id
|
|
33
|
+
@payload = payload
|
|
34
|
+
if pattern
|
|
35
|
+
self["pattern"] = pattern
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def post_process
|
|
40
|
+
self["loc"] = Util.strip_uri_values(@raw_location)
|
|
41
|
+
if @user_id
|
|
42
|
+
self["uid"] = @user_id.to_s
|
|
43
|
+
end
|
|
44
|
+
if @transaction_id
|
|
45
|
+
self["tid"] = @transaction_id
|
|
46
|
+
end
|
|
47
|
+
if @raw_session_id
|
|
48
|
+
hmac_key = Util.getHmacKey()
|
|
49
|
+
self["sid"] = Util.hmac(@raw_session_id, hmac_key)
|
|
50
|
+
end
|
|
51
|
+
if @payload
|
|
52
|
+
self["payload"] = @payload[0..150]
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# See the file "LICENSE" for the full license governing this code.
|
|
3
|
+
|
|
4
|
+
require 'tcell_agent/sensor_events/sensor'
|
|
5
|
+
|
|
6
|
+
require 'tcell_agent/agent'
|
|
7
|
+
require 'tcell_agent/agent/policy_types'
|
|
8
|
+
require 'tcell_agent/policies/appsensor_policy'
|
|
9
|
+
|
|
10
|
+
# Some Rules Originate from ModSecurity
|
|
11
|
+
# ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
|
12
|
+
# Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
|
13
|
+
|
|
14
|
+
module TCellAgent
|
|
15
|
+
module SensorEvents
|
|
16
|
+
|
|
17
|
+
class AppSensorMetaEvent < TCellSensorEvent
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
def build(request, rack_response, response_code, response_headers)
|
|
21
|
+
meta_event = AppSensorMetaEvent.new
|
|
22
|
+
|
|
23
|
+
meta_event.remote_address = request.ip
|
|
24
|
+
meta_event.method = request.request_method
|
|
25
|
+
meta_event.location = "#{request.base_url}#{request.fullpath}"
|
|
26
|
+
meta_event.request_headers = request.env
|
|
27
|
+
meta_event.request_content_len = (request.content_length || "0").to_i
|
|
28
|
+
meta_event.response_content_len = (rack_response.length || "0").to_i
|
|
29
|
+
meta_event.get_dict = request.GET
|
|
30
|
+
meta_event.post_dict = request.POST
|
|
31
|
+
meta_event.cookie_dict = request.cookies
|
|
32
|
+
|
|
33
|
+
meta_event.response_code = response_code
|
|
34
|
+
meta_event.response_headers = response_headers
|
|
35
|
+
|
|
36
|
+
meta_event.route_id = request.env["tcell.request_data"].route_id
|
|
37
|
+
meta_event.transaction_id = request.env["tcell.request_data"].transaction_id
|
|
38
|
+
meta_event.session_id = request.env["tcell.request_data"].hmac_session_id
|
|
39
|
+
meta_event.user_id = request.env["tcell.request_data"].user_id
|
|
40
|
+
|
|
41
|
+
meta_event.set_body_dict(
|
|
42
|
+
meta_event.request_content_len,
|
|
43
|
+
request.content_type,
|
|
44
|
+
request.body.gets
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
meta_event
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
attr_accessor :remote_address, :method, :location, :route_id, :session_id, :user_id, :transaction_id,
|
|
53
|
+
:request_content_len, :get_dict, :post_dict, :body_dict, :cookie_dict, :response_content_len, :response_code
|
|
54
|
+
|
|
55
|
+
attr_accessor :request_headers, :response_headers
|
|
56
|
+
|
|
57
|
+
def initialize
|
|
58
|
+
@request_content_len = 0
|
|
59
|
+
@response_content_len = 0
|
|
60
|
+
@send = false
|
|
61
|
+
@body_dict = {}
|
|
62
|
+
@get_dict = {}
|
|
63
|
+
@post_dict = {}
|
|
64
|
+
@cookie_dict = {}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def set_body_dict(request_content_len, request_content_type, request_body)
|
|
68
|
+
if request_content_len > 2000000
|
|
69
|
+
@body_dict = {}
|
|
70
|
+
|
|
71
|
+
else
|
|
72
|
+
if request_content_type =~ %r{application/json}i && request_body
|
|
73
|
+
begin
|
|
74
|
+
@body_dict = JSON.parse(request_body)
|
|
75
|
+
rescue
|
|
76
|
+
TCellAgent.logger.debug("JSON body parameter parsing failed")
|
|
77
|
+
@body_dict = {}
|
|
78
|
+
end
|
|
79
|
+
else
|
|
80
|
+
@body_dict = {}
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def post_process
|
|
86
|
+
appsensor_policy = TCellAgent.policy(TCellAgent::PolicyTypes::AppSensor)
|
|
87
|
+
return unless appsensor_policy
|
|
88
|
+
|
|
89
|
+
appsensor_policy.process_meta_event(self)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -2,19 +2,28 @@
|
|
|
2
2
|
# `bundle exec rails s` command. The appropriate server will be
|
|
3
3
|
# launched through Rack::Server interface
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
require("tcell_agent/servers/webrick") if defined?(Rack::Handler::WEBrick)
|
|
7
|
-
require("tcell_agent/servers/thin") if defined?(Thin::Server)
|
|
5
|
+
Rails::Server.class_eval do
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
alias_method :tcell_start, :start
|
|
8
|
+
def start(&blk)
|
|
9
|
+
require("tcell_agent/servers/unicorn") if defined?(Unicorn::HttpServer)
|
|
10
|
+
require("tcell_agent/servers/webrick") if defined?(Rack::Handler::WEBrick)
|
|
11
|
+
require("tcell_agent/servers/thin") if defined?(Thin::Server)
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
TCellAgent.run_instrumentation("Puma Single Mode")
|
|
13
|
+
if defined?(Puma::Server)
|
|
14
|
+
Puma::Server.class_eval do
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
alias_method :original_run, :run
|
|
17
|
+
def run(background=true)
|
|
18
|
+
TCellAgent.run_instrumentation("Puma Single Mode")
|
|
19
|
+
|
|
20
|
+
original_run(background)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
17
24
|
end
|
|
18
25
|
|
|
26
|
+
tcell_start(&blk)
|
|
19
27
|
end
|
|
28
|
+
|
|
20
29
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module TCellAgent
|
|
2
|
+
module Utils
|
|
3
|
+
module Params
|
|
4
|
+
GET_PARAM = "get"
|
|
5
|
+
POST_PARAM = "post"
|
|
6
|
+
JSON_PARAM = "json"
|
|
7
|
+
COOKIE_PARAM = "cookies"
|
|
8
|
+
|
|
9
|
+
def param_deep_loop(param_name, param_value, &block)
|
|
10
|
+
return nil unless param_name and param_value
|
|
11
|
+
|
|
12
|
+
if param_value.is_a?(Hash)
|
|
13
|
+
param_value.each do |k, v|
|
|
14
|
+
result = param_deep_loop(k, v, &block)
|
|
15
|
+
if result
|
|
16
|
+
return result
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
elsif param_value.is_a?(Array)
|
|
21
|
+
param_value.each do |v|
|
|
22
|
+
result = param_deep_loop(param_name, v, &block)
|
|
23
|
+
return result if result
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
elsif param_value.is_a?(String)
|
|
27
|
+
#if isinstance(param_value, bytes):
|
|
28
|
+
#param_value = param_value.decode('utf-8')
|
|
29
|
+
#param_type = str(type(param_value))
|
|
30
|
+
|
|
31
|
+
match = block.call(param_name, param_value)
|
|
32
|
+
return match if match
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
return nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/tcell_agent/version.rb
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module TCellAgent
|
|
4
|
+
|
|
5
|
+
describe AppSensorRuleManager do
|
|
6
|
+
describe "#initialize" do
|
|
7
|
+
context "loading default baserules" do
|
|
8
|
+
it "should initialize all the sensors" do
|
|
9
|
+
rule_manager = AppSensorRuleManager.new(get_test_resource_path("baserules.json"))
|
|
10
|
+
|
|
11
|
+
expect(rule_manager.rule_info.empty?).to eq(false)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "#load_rules_file" do
|
|
17
|
+
context "with nonexistent file" do
|
|
18
|
+
it "should do nothing" do
|
|
19
|
+
rule_manager = AppSensorRuleManager.new()
|
|
20
|
+
rule_manager.load_rules_file("non-existent-file.json")
|
|
21
|
+
|
|
22
|
+
expect(rule_manager.rule_info.empty?).to eq(true)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "#load_default_rules_file" do
|
|
28
|
+
it "should attempt to load default rules file" do
|
|
29
|
+
expect_any_instance_of(AppSensorRuleManager).to receive(:load_rules_file).with(
|
|
30
|
+
/tcell_agent\/appsensor\/rules\/baserules.json/
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
rule_manager = AppSensorRuleManager.new()
|
|
34
|
+
rule_manager.load_default_rules_file()
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module TCellAgent
|
|
4
|
+
|
|
5
|
+
describe AppSensorRuleSet do
|
|
6
|
+
|
|
7
|
+
describe "#add_pattern_from_dict" do
|
|
8
|
+
context "adding from nil dict" do
|
|
9
|
+
it "should do nothing" do
|
|
10
|
+
rule_set = AppSensorRuleSet.new
|
|
11
|
+
rule_set.add_pattern_from_dict(nil)
|
|
12
|
+
expect(rule_set.safe_pattern).to eq(nil)
|
|
13
|
+
expect(rule_set.patterns).to eq([])
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context "adding from empty dict" do
|
|
18
|
+
it "should do nothing" do
|
|
19
|
+
rule_set = AppSensorRuleSet.new
|
|
20
|
+
rule_set.add_pattern_from_dict({})
|
|
21
|
+
expect(rule_set.safe_pattern).to eq(nil)
|
|
22
|
+
expect(rule_set.patterns).to eq([])
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context "adding a ruby pattern" do
|
|
27
|
+
it "should add the pattern" do
|
|
28
|
+
rule_set = AppSensorRuleSet.new
|
|
29
|
+
rule_set.add_pattern_from_dict({
|
|
30
|
+
"id" => 1,
|
|
31
|
+
"common" => "<(iframe)",
|
|
32
|
+
"ruby" => "<(script)"
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
expect(rule_set.safe_pattern).to eq(nil)
|
|
36
|
+
expect(rule_set.patterns.size).to eq(1)
|
|
37
|
+
|
|
38
|
+
arp = rule_set.patterns[0]
|
|
39
|
+
expect(arp.enabled).to eq(true)
|
|
40
|
+
expect(arp.pattern_id).to eq(1)
|
|
41
|
+
expect(arp.pattern_regex).to_not eq(nil)
|
|
42
|
+
expect("<script".match(arp.pattern_regex).captures).to eq(["script"])
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "adding a common pattern" do
|
|
47
|
+
it "should add the pattern" do
|
|
48
|
+
rule_set = AppSensorRuleSet.new
|
|
49
|
+
rule_set.add_pattern_from_dict({
|
|
50
|
+
"id" => 1,
|
|
51
|
+
"common" => "<(script|iframe|embed|frame|frameset|object|img|applet|body|html|style|layer|link|ilayer|meta|bgsound)"
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
expect(rule_set.safe_pattern).to eq(nil)
|
|
55
|
+
expect(rule_set.patterns.size).to eq(1)
|
|
56
|
+
|
|
57
|
+
arp = rule_set.patterns[0]
|
|
58
|
+
expect(arp.enabled).to eq(true)
|
|
59
|
+
expect(arp.pattern_id).to eq(1)
|
|
60
|
+
expect(arp.pattern_regex).to_not eq(nil)
|
|
61
|
+
expect("<script".match(arp.pattern_regex).captures).to eq(["script"])
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe "#set_safe_pattern_from_string" do
|
|
67
|
+
it "should set the safe pattern" do
|
|
68
|
+
rule_set = AppSensorRuleSet.new
|
|
69
|
+
rule_set.set_safe_pattern_from_string("^[a-zA-Z0-9_\s\r\n\t]*$")
|
|
70
|
+
|
|
71
|
+
expect(rule_set.safe_pattern).to eq(Regexp.new("^[a-zA-Z0-9_\s\r\n\t]*$"))
|
|
72
|
+
expect(rule_set.patterns.size).to eq(0)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe "#check_violation" do
|
|
77
|
+
before(:each) do
|
|
78
|
+
@rule_set = AppSensorRuleSet.new
|
|
79
|
+
@rule_set.set_safe_pattern_from_string("super_safe")
|
|
80
|
+
@rule_set.add_pattern_from_dict({
|
|
81
|
+
"id" => 1,
|
|
82
|
+
"common" => "<(script)"
|
|
83
|
+
})
|
|
84
|
+
@rule_set.add_pattern_from_dict({
|
|
85
|
+
"id" => 2,
|
|
86
|
+
"common" => "<(iframe)"
|
|
87
|
+
})
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context "param value is nil" do
|
|
91
|
+
it "should return nil" do
|
|
92
|
+
expect(@rule_set.check_violation(nil, nil, {}, true)).to eq(nil)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context "param value is empty" do
|
|
97
|
+
it "should return nil" do
|
|
98
|
+
expect(@rule_set.check_violation(nil, nil, {}, true)).to eq(nil)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context "param value is present" do
|
|
103
|
+
context "param value matches safe pattern" do
|
|
104
|
+
it "should return nil" do
|
|
105
|
+
expect(@rule_set.check_violation("param_name", "super_safe", {}, true)).to eq(nil)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context "param value does not match anything" do
|
|
110
|
+
it "should return nil" do
|
|
111
|
+
expect(@rule_set.check_violation("param_name", "weeee", {}, true)).to eq(nil)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
context "param value matches a pattern" do
|
|
116
|
+
it "should return the match" do
|
|
117
|
+
match_data = @rule_set.check_violation("param_name", "evil <script>", {}, true)
|
|
118
|
+
expect(match_data).to eq({"param"=>"param_name", "value"=>"evil <script>", "pattern"=>1})
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context "v1_compatability is off" do
|
|
123
|
+
context "all patterns are disabled" do
|
|
124
|
+
context "param value contains evil pattern" do
|
|
125
|
+
it "should return nil" do
|
|
126
|
+
match_data = @rule_set.check_violation("param_name", "evil <script>", {}, false)
|
|
127
|
+
expect(match_data).to eq(nil)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
context "one pattern is disabled" do
|
|
133
|
+
context "evil param_value matches disabled pattern" do
|
|
134
|
+
it "should return nil" do
|
|
135
|
+
match_data = @rule_set.check_violation("param_name", "evil <script>", {2 => true}, false)
|
|
136
|
+
expect(match_data).to eq(nil)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
context "evil param_value matches enabled pattern" do
|
|
141
|
+
it "should return the match" do
|
|
142
|
+
match_data = @rule_set.check_violation("param_name", "evil <iframe>", {2 => true}, false)
|
|
143
|
+
expect(match_data).to eq({"param"=>"param_name", "value"=>"evil <iframe>", "pattern"=>2})
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
end
|