tcell_agent 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +4 -0
- data/README.md +43 -0
- data/Rakefile +7 -0
- data/bin/tcell_agent +171 -0
- data/config/initializers/authlogic_auth.rb +51 -0
- data/config/initializers/devise_auth.rb +167 -0
- data/config/initializers/init.rb +8 -0
- data/lib/tcell_agent.rb +33 -0
- data/lib/tcell_agent/agent.rb +79 -0
- data/lib/tcell_agent/agent/event_processor.rb +133 -0
- data/lib/tcell_agent/agent/policy_manager.rb +138 -0
- data/lib/tcell_agent/agent/policy_types.rb +42 -0
- data/lib/tcell_agent/agent/static_agent.rb +22 -0
- data/lib/tcell_agent/api.rb +101 -0
- data/lib/tcell_agent/appsensor.rb +42 -0
- data/lib/tcell_agent/appsensor/cmdi.rb +32 -0
- data/lib/tcell_agent/appsensor/path_traversal.rb +33 -0
- data/lib/tcell_agent/appsensor/sqli.rb +55 -0
- data/lib/tcell_agent/appsensor/xss.rb +40 -0
- data/lib/tcell_agent/authlogic.rb +26 -0
- data/lib/tcell_agent/configuration.rb +148 -0
- data/lib/tcell_agent/dataloss.rb +0 -0
- data/lib/tcell_agent/devise.rb +83 -0
- data/lib/tcell_agent/instrumentation.rb +44 -0
- data/lib/tcell_agent/logger.rb +46 -0
- data/lib/tcell_agent/policies/add_script_tag_policy.rb +47 -0
- data/lib/tcell_agent/policies/appsensor_policy.rb +76 -0
- data/lib/tcell_agent/policies/clickjacking_policy.rb +113 -0
- data/lib/tcell_agent/policies/content_security_policy.rb +119 -0
- data/lib/tcell_agent/policies/dataloss_policy.rb +175 -0
- data/lib/tcell_agent/policies/honeytokens_policy.rb +67 -0
- data/lib/tcell_agent/policies/http_redirect_policy.rb +84 -0
- data/lib/tcell_agent/policies/http_tx_policy.rb +60 -0
- data/lib/tcell_agent/policies/login_fraud_policy.rb +42 -0
- data/lib/tcell_agent/policies/secure_headers_policy.rb +64 -0
- data/lib/tcell_agent/rails.rb +146 -0
- data/lib/tcell_agent/rails/devise.rb +0 -0
- data/lib/tcell_agent/rails/dlp.rb +204 -0
- data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +69 -0
- data/lib/tcell_agent/rails/middleware/context_middleware.rb +50 -0
- data/lib/tcell_agent/rails/middleware/global_middleware.rb +53 -0
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +176 -0
- data/lib/tcell_agent/rails/routes.rb +130 -0
- data/lib/tcell_agent/rails/settings_reporter.rb +40 -0
- data/lib/tcell_agent/sensor_events/app_config.rb +16 -0
- data/lib/tcell_agent/sensor_events/app_sensor.rb +240 -0
- data/lib/tcell_agent/sensor_events/dlp.rb +58 -0
- data/lib/tcell_agent/sensor_events/honeytokens.rb +16 -0
- data/lib/tcell_agent/sensor_events/login_fraud.rb +43 -0
- data/lib/tcell_agent/sensor_events/metrics.rb +24 -0
- data/lib/tcell_agent/sensor_events/sensor.rb +85 -0
- data/lib/tcell_agent/sensor_events/server_agent.rb +101 -0
- data/lib/tcell_agent/sensor_events/util/redirect_utils.rb +22 -0
- data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +153 -0
- data/lib/tcell_agent/sensor_events/util/utils.rb +21 -0
- data/lib/tcell_agent/sinatra.rb +41 -0
- data/lib/tcell_agent/start_background_thread.rb +63 -0
- data/lib/tcell_agent/userinfo.rb +8 -0
- data/lib/tcell_agent/utils/queue_with_timeout.rb +60 -0
- data/lib/tcell_agent/version.rb +5 -0
- data/spec/controllers/application_controller.rb +12 -0
- data/spec/lib/tcell_agent/api/api_spec.rb +36 -0
- data/spec/lib/tcell_agent/appsensor_spec.rb +66 -0
- data/spec/lib/tcell_agent/policies/add_script_tag_policy_spec.rb +37 -0
- data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +40 -0
- data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +71 -0
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +71 -0
- data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +88 -0
- data/spec/lib/tcell_agent/policies/honeytokens_policy_spec.rb +22 -0
- data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +62 -0
- data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +22 -0
- data/spec/lib/tcell_agent/policies/login_policy_spec.rb +42 -0
- data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +67 -0
- data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +187 -0
- data/spec/lib/tcell_agent/rails_spec.rb +57 -0
- data/spec/lib/tcell_agent/sensor_events/dlp_spec.rb +14 -0
- data/spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb +25 -0
- data/spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb +57 -0
- data/spec/lib/tcell_agent_spec.rb +22 -0
- data/spec/resources/normal_config.json +13 -0
- data/spec/spec_helper.rb +4 -0
- data/tcell_agent.gemspec +29 -0
- metadata +249 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
require 'uri'
|
5
|
+
require 'tcell_agent/logger'
|
6
|
+
require 'tcell_agent/agent'
|
7
|
+
require 'tcell_agent/sensor_events/sensor'
|
8
|
+
require 'tcell_agent/sensor_events/app_sensor'
|
9
|
+
require 'tcell_agent/sensor_events/server_agent'
|
10
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
11
|
+
require 'tcell_agent/sensor_events/util/redirect_utils'
|
12
|
+
|
13
|
+
require 'tcell_agent/rails/routes'
|
14
|
+
|
15
|
+
require 'tcell_agent/userinfo'
|
16
|
+
require 'cgi'
|
17
|
+
|
18
|
+
require 'tcell_agent/instrumentation'
|
19
|
+
|
20
|
+
module TCellAgent
|
21
|
+
module Instrumentation
|
22
|
+
module Rails
|
23
|
+
module Middleware
|
24
|
+
|
25
|
+
class GlobalMiddleware
|
26
|
+
|
27
|
+
def initialize(app)
|
28
|
+
@app = app
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(env)
|
32
|
+
request = Rack::Request.new(env)
|
33
|
+
TCellAgent::Instrumentation.safe_block("Setting session_id & user_id") {
|
34
|
+
if request.session
|
35
|
+
env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID].session_id = request.session["session_id"]
|
36
|
+
env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID].user_id = TCellAgent::UserInformation.getUserFromRequest(request)
|
37
|
+
end
|
38
|
+
}
|
39
|
+
TCellAgent::Instrumentation.safe_block("Setting hmac_session_id") {
|
40
|
+
hmac_key = TCellAgent::SensorEvents::Util.getHmacKey()
|
41
|
+
if request.env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID].session_id
|
42
|
+
env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID].hmac_session_id = TCellAgent::SensorEvents::Util.hmac(request.env["tcell.request_data"].session_id, hmac_key)
|
43
|
+
end
|
44
|
+
}
|
45
|
+
response = @app.call(env)
|
46
|
+
response
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
require 'uri'
|
5
|
+
require 'tcell_agent/logger'
|
6
|
+
require 'tcell_agent/agent'
|
7
|
+
require 'tcell_agent/sensor_events/sensor'
|
8
|
+
require 'tcell_agent/sensor_events/app_sensor'
|
9
|
+
require 'tcell_agent/sensor_events/server_agent'
|
10
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
11
|
+
require 'tcell_agent/sensor_events/util/redirect_utils'
|
12
|
+
|
13
|
+
require 'tcell_agent/rails/routes'
|
14
|
+
|
15
|
+
require 'tcell_agent/userinfo'
|
16
|
+
require 'cgi'
|
17
|
+
|
18
|
+
require 'tcell_agent/instrumentation'
|
19
|
+
|
20
|
+
module TCellAgent
|
21
|
+
module Instrumentation
|
22
|
+
module Rails
|
23
|
+
module Middleware
|
24
|
+
|
25
|
+
class HeadersMiddleware
|
26
|
+
|
27
|
+
def initialize(app)
|
28
|
+
@app = app
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(env)
|
32
|
+
|
33
|
+
request = Rack::Request.new(env)
|
34
|
+
response = @app.call(env)
|
35
|
+
status, headers, active_response = response
|
36
|
+
TCellAgent::Instrumentation.safe_block("Handling Request") {
|
37
|
+
tcell_response = response
|
38
|
+
tcell_response = self._handle_appsensor(request, tcell_response)
|
39
|
+
tcell_response = self._handle_redirect(request, tcell_response)
|
40
|
+
tcell_response = self._set_csp_header(request, tcell_response)
|
41
|
+
tcell_response = self._set_clickjacking_header(request, tcell_response)
|
42
|
+
tcell_response = self._set_secure_headers(request, tcell_response)
|
43
|
+
response = tcell_response
|
44
|
+
}
|
45
|
+
response
|
46
|
+
end
|
47
|
+
|
48
|
+
def _set_csp_header(request, response)
|
49
|
+
TCellAgent::Instrumentation.safe_block("Setting CSP Headers") {
|
50
|
+
status, headers, active_response = response
|
51
|
+
|
52
|
+
content_security_policy = TCellAgent.policy(TCellAgent::PolicyTypes::CSP)
|
53
|
+
|
54
|
+
if content_security_policy
|
55
|
+
content_security_policy.each(
|
56
|
+
request.env["tcell.request_data"].transaction_id,
|
57
|
+
request.env["tcell.request_data"].hmac_session_id,
|
58
|
+
request.env["tcell.request_data"].user_id) do | header_pair |
|
59
|
+
headers[header_pair["name"]] = header_pair["value"]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
response = [status, headers, active_response]
|
63
|
+
}
|
64
|
+
response
|
65
|
+
end
|
66
|
+
|
67
|
+
def _set_clickjacking_header(request, response)
|
68
|
+
TCellAgent::Instrumentation.safe_block("Setting Clickjacking Headers") {
|
69
|
+
status, headers, active_response = response
|
70
|
+
clickjacking_policy = TCellAgent.policy(TCellAgent::PolicyTypes::Clickjacking)
|
71
|
+
|
72
|
+
if clickjacking_policy
|
73
|
+
clickjacking_policy.each(
|
74
|
+
request.env["tcell.request_data"].transaction_id,
|
75
|
+
request.env["tcell.request_data"].hmac_session_id,
|
76
|
+
request.env["tcell.request_data"].user_id) do | header_pair |
|
77
|
+
header_name = header_pair["name"]
|
78
|
+
header_value = header_pair["value"]
|
79
|
+
if (headers.has_key?header_name)
|
80
|
+
headers[header_name] = headers[header_name] + "," + header_value
|
81
|
+
else
|
82
|
+
headers[header_name] = header_value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end #if
|
86
|
+
|
87
|
+
response = [status, headers, active_response]
|
88
|
+
}
|
89
|
+
response
|
90
|
+
end
|
91
|
+
|
92
|
+
def _set_secure_headers(request, response)
|
93
|
+
TCellAgent::Instrumentation.safe_block("Setting Secure Headers") {
|
94
|
+
status, headers, active_response = response
|
95
|
+
|
96
|
+
secure_headers_policy = TCellAgent.policy(TCellAgent::PolicyTypes::SecureHeaders)
|
97
|
+
if secure_headers_policy
|
98
|
+
secure_headers_policy.headers.each do | secure_header |
|
99
|
+
headers[secure_header.name] = secure_header.value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
response = [status, headers, active_response]
|
103
|
+
}
|
104
|
+
response
|
105
|
+
end
|
106
|
+
|
107
|
+
def _handle_redirect(request, response)
|
108
|
+
TCellAgent::Instrumentation.safe_block("Handling Redirect Headers") {
|
109
|
+
status, headers, active_response = response
|
110
|
+
|
111
|
+
http_redirect_policy = TCellAgent.policy(TCellAgent::PolicyTypes::HttpRedirect)
|
112
|
+
if http_redirect_policy && headers.has_key?("Location")
|
113
|
+
local_uri = URI.parse(request.url)
|
114
|
+
new_location = http_redirect_policy.enforce(
|
115
|
+
headers["Location"],
|
116
|
+
local_uri.host,
|
117
|
+
request.fullpath,
|
118
|
+
request.request_method,
|
119
|
+
status,
|
120
|
+
request.ip)
|
121
|
+
# Enforcement
|
122
|
+
if (new_location)
|
123
|
+
headers["Location"] = new_location
|
124
|
+
end
|
125
|
+
end
|
126
|
+
response = [status, headers, active_response]
|
127
|
+
}
|
128
|
+
response
|
129
|
+
end
|
130
|
+
|
131
|
+
def _handle_appsensor(request, response)
|
132
|
+
TCellAgent::Instrumentation.safe_block("Handling AppSensor") {
|
133
|
+
status_code, response_headers, response_body = response
|
134
|
+
appsensor_policy = TCellAgent.policy(TCellAgent::PolicyTypes::AppSensor)
|
135
|
+
|
136
|
+
if (!(response_body.is_a?(Array)) && !(response_body.is_a?(Rack::BodyProxy)))
|
137
|
+
return response
|
138
|
+
end
|
139
|
+
rack_response = Rack::Response.new(response)
|
140
|
+
if appsensor_policy && appsensor_policy.enabled
|
141
|
+
event = TCellAgent::SensorEvents::TCellAppSensorEventProcessor.new
|
142
|
+
event.request_headers = request.env
|
143
|
+
event.request_content_length = (request.content_length || "0").to_i
|
144
|
+
event.request_body = request.body
|
145
|
+
event.response_content_length = (rack_response.length || "0").to_i
|
146
|
+
event.remote_addr = request.ip
|
147
|
+
event.uri = request.fullpath
|
148
|
+
event.get_params = request.GET
|
149
|
+
event.post_params = request.POST
|
150
|
+
event.cookies = request.cookies
|
151
|
+
|
152
|
+
#status, headers, active_response = response
|
153
|
+
#if active_response.class != ActionDispatch::Response
|
154
|
+
# return response
|
155
|
+
#end
|
156
|
+
|
157
|
+
event.status_code = status_code
|
158
|
+
event.response_headers = response_headers
|
159
|
+
event.response_body = response_body
|
160
|
+
|
161
|
+
event.route_id = request.env["tcell.request_data"].route_id
|
162
|
+
event.transaction_id = request.env["tcell.request_data"].transaction_id
|
163
|
+
event.session_id = request.env["tcell.request_data"].hmac_session_id
|
164
|
+
event.user_id = request.env["tcell.request_data"].user_id
|
165
|
+
|
166
|
+
TCellAgent.send_event(event)
|
167
|
+
end
|
168
|
+
}
|
169
|
+
response
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
|
2
|
+
module TCellAgent
|
3
|
+
class Engine < Rails::Engine
|
4
|
+
ActiveSupport.on_load(:action_controller) do
|
5
|
+
ActionController::Base.class_eval do
|
6
|
+
around_filter :tell_around_filter_routes
|
7
|
+
def tell_around_filter_routes
|
8
|
+
begin
|
9
|
+
TCellAgent::Instrumentation.safe_block("Determining Rails Route ID") {
|
10
|
+
route = Rails.application.routes.router.recognize(request) { |route, _| route }.first
|
11
|
+
if route
|
12
|
+
route_path = route[2].path.spec
|
13
|
+
tcell_context = request.env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID]
|
14
|
+
tcell_context.route_id = TCellAgent::SensorEvents::Util.calculateRouteId(request.method.downcase, route_path)
|
15
|
+
end
|
16
|
+
}
|
17
|
+
yield
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
module TCellAgent
|
28
|
+
module Instrumentation
|
29
|
+
module Rails
|
30
|
+
def self.route_path_from_route(route)
|
31
|
+
if (::Rails::VERSION::MAJOR == 4)
|
32
|
+
begin
|
33
|
+
route_path = "#{route[2].path.spec}"
|
34
|
+
if (route_path.end_with?("(.:format)"))
|
35
|
+
route_path = route_path.chomp("(.:format)")
|
36
|
+
end
|
37
|
+
return route_path
|
38
|
+
rescue Exception => inner_excetion
|
39
|
+
TCellAgent.logger.debug("Could not figure out path #{inner_excetion.message}")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
def self.route_from_request(rails_request)
|
45
|
+
if (rails_request.env["action_dispatch.request_id"] == nil)
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
if (::Rails::VERSION::MAJOR == 4)
|
49
|
+
begin
|
50
|
+
recognized = ::Rails.application.routes.router.recognize(rails_request) { |route, _| route }
|
51
|
+
if recognized
|
52
|
+
return recognized.first
|
53
|
+
end
|
54
|
+
rescue Exception => inner_excetion
|
55
|
+
TCellAgent.logger.debug("Could not figure out path #{inner_excetion.message}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
def self.route_id_from_request(active_request)
|
61
|
+
route = route_from_request(active_request)
|
62
|
+
if route != nil
|
63
|
+
route_path = route_path_from_route(route)
|
64
|
+
if route_path != nil
|
65
|
+
return TCellAgent::SensorEvents::Util.calculateRouteId(active_request.request_method.downcase, route_path)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
def self.get_routes
|
71
|
+
end
|
72
|
+
if (::Rails::VERSION::MAJOR == 3)
|
73
|
+
ActionDispatch::Routing::RouteSet.class_eval do
|
74
|
+
alias_method :original_add_route, :add_route
|
75
|
+
def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true)
|
76
|
+
methods = ['GET','POST','PUT','DELETE','HEAD',
|
77
|
+
'PATCH','TRACE','CONNECT','OPTIONS']
|
78
|
+
route = original_add_route(app, conditions, requirements, defaults, name, anchor)
|
79
|
+
if (route.constraints.has_key? :request_method)
|
80
|
+
route_path = "#{route.path.spec}"
|
81
|
+
if (route_path.end_with?("(.:format)"))
|
82
|
+
route_path = route_path.chomp("(.:format)")
|
83
|
+
end
|
84
|
+
route_destination = route.defaults.to_json.to_s
|
85
|
+
route_params = route.path.required_names
|
86
|
+
route_methods = methods.select {|x| route.verb.match(x) }
|
87
|
+
route_methods.each { |route_method|
|
88
|
+
route_id = TCellAgent::SensorEvents::Util.calculateRouteId(route_method.downcase, route.path.spec)
|
89
|
+
TCellAgent.send_event(
|
90
|
+
TCellAgent::SensorEvents::AppRoutesSensorEvent.new(
|
91
|
+
route_path, route_method, route_id, nil, route_destination
|
92
|
+
)
|
93
|
+
)
|
94
|
+
}
|
95
|
+
end
|
96
|
+
route
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
if (::Rails::VERSION::MAJOR == 4)
|
101
|
+
ActionDispatch::Journey::Routes.class_eval do
|
102
|
+
alias_method :original_add_route, :add_route
|
103
|
+
def add_route(app, path, conditions, defaults, name = nil)
|
104
|
+
methods = ['GET','POST','PUT','DELETE','HEAD',
|
105
|
+
'PATCH','TRACE','CONNECT','OPTIONS']
|
106
|
+
route = original_add_route(app, path, conditions, defaults, name)
|
107
|
+
if (route.constraints.has_key? :request_method)
|
108
|
+
route_path = "#{route.path.spec}"
|
109
|
+
if (route_path.end_with?("(.:format)"))
|
110
|
+
route_path = route_path.chomp("(.:format)")
|
111
|
+
end
|
112
|
+
route_destination = route.defaults.to_json.to_s
|
113
|
+
route_params = route.path.required_names
|
114
|
+
route_methods = methods.select {|x| route.verb.match(x) }
|
115
|
+
route_methods.each { |route_method|
|
116
|
+
route_id = TCellAgent::SensorEvents::Util.calculateRouteId(route_method.downcase, route.path.spec)
|
117
|
+
TCellAgent.send_event(
|
118
|
+
TCellAgent::SensorEvents::AppRoutesSensorEvent.new(
|
119
|
+
route_path, route_method, route_id, nil, route_destination
|
120
|
+
)
|
121
|
+
)
|
122
|
+
}
|
123
|
+
end
|
124
|
+
route
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end #endif rails version = 4
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'tcell_agent'
|
3
|
+
require 'tcell_agent/sensor_events/app_config'
|
4
|
+
require 'tcell_agent/sensor_events/server_agent'
|
5
|
+
|
6
|
+
module TCellAgent
|
7
|
+
module Instrumentation
|
8
|
+
module Rails
|
9
|
+
def self.send_framework_info
|
10
|
+
if (TCellAgent.configuration.exp_config_settings)
|
11
|
+
version = ::Rails.version
|
12
|
+
TCellAgent.send_event(TCellAgent::SensorEvents::ServerAgentAppFrameworkEvent.new(
|
13
|
+
"Rails", version
|
14
|
+
))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
def self.send_settings(application)
|
18
|
+
if (TCellAgent.configuration.exp_config_settings)
|
19
|
+
# Defaults to true
|
20
|
+
csrf_protection = application.config.action_controller.allow_forgery_protection || true
|
21
|
+
TCellAgent.send_event(TCellAgent::SensorEvents::AppConfigSettingEvent.new(
|
22
|
+
"Rails", "core", "", "csrf_protection", csrf_protection
|
23
|
+
))
|
24
|
+
|
25
|
+
# Defaults to false if nil
|
26
|
+
mass_assignment_allowed = application.config.action_controller.permit_all_parameters || false
|
27
|
+
TCellAgent.send_event(TCellAgent::SensorEvents::AppConfigSettingEvent.new(
|
28
|
+
"Rails", "core", "", "mass_assignment_allowed", mass_assignment_allowed
|
29
|
+
))
|
30
|
+
|
31
|
+
# Defaults to never
|
32
|
+
session_expire = application.config.session_options[:expire_after] || -1
|
33
|
+
TCellAgent.send_event(TCellAgent::SensorEvents::AppConfigSettingEvent.new(
|
34
|
+
"Rails", "session", "", "timeout", session_expire
|
35
|
+
))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'tcell_agent/sensor_events/sensor'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module SensorEvents
|
5
|
+
class AppConfigSettingEvent < TCellSensorEvent
|
6
|
+
def initialize(package, section, prefix, name, value)
|
7
|
+
super("app_config_setting")
|
8
|
+
self["package"] = package
|
9
|
+
self["section"] = section
|
10
|
+
self["prefix"] = prefix
|
11
|
+
self["name"] = name
|
12
|
+
self["value"] = value.to_s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# See the file "LICENSE" for the full license governing this code.
|
3
|
+
|
4
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
5
|
+
require 'tcell_agent/sensor_events/sensor'
|
6
|
+
|
7
|
+
require 'tcell_agent/agent'
|
8
|
+
require 'tcell_agent/agent/policy_types'
|
9
|
+
|
10
|
+
require 'tcell_agent/policies/appsensor_policy'
|
11
|
+
require 'tcell_agent/appsensor'
|
12
|
+
|
13
|
+
require 'tcell_agent/instrumentation'
|
14
|
+
|
15
|
+
# Some Rules Originate from ModSecurity
|
16
|
+
# ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
17
|
+
# Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
18
|
+
|
19
|
+
module TCellAgent
|
20
|
+
module SensorEvents
|
21
|
+
class TCellAppSensorEvent < TCellSensorEvent
|
22
|
+
def initialize(location, detection_point, remote_addr, param, route_id, data=nil, transaction_id=nil, session_id=nil, user_id=nil)
|
23
|
+
super("as")
|
24
|
+
self["dp"] = detection_point
|
25
|
+
self["param"] = param
|
26
|
+
self["remote_addr"] = remote_addr
|
27
|
+
if (route_id)
|
28
|
+
self["rou"] = route_id
|
29
|
+
end
|
30
|
+
@raw_location = location
|
31
|
+
@user_id = user_id
|
32
|
+
@transaction_id = transaction_id
|
33
|
+
@raw_session_id = session_id
|
34
|
+
end
|
35
|
+
def post_process
|
36
|
+
self["loc"] = Util.strip_uri_values(@raw_location)
|
37
|
+
if @user_id
|
38
|
+
self["uid"] = @user_id.to_s
|
39
|
+
end
|
40
|
+
if @transaction_id
|
41
|
+
self["tid"] = @transaction_id
|
42
|
+
end
|
43
|
+
if @raw_session_id
|
44
|
+
hmac_key = Util.getHmacKey()
|
45
|
+
self["sid"] = Util.hmac(@raw_session_id, hmac_key)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
class TCellAppSensorEventProcessor < TCellSensorEvent
|
50
|
+
attr_accessor :request_headers, :request_body, :remote_addr,
|
51
|
+
:uri, :get_params, :post_params, :cookies,
|
52
|
+
:request_content_length, :request_content_type
|
53
|
+
attr_accessor :status_code, :response_headers, :response_body,
|
54
|
+
:response_content_length,
|
55
|
+
:route_id, :transaction_id, :session_id, :user_id
|
56
|
+
def initialize
|
57
|
+
@request_content_length=0
|
58
|
+
@response_content_length = 0
|
59
|
+
@send = false
|
60
|
+
end
|
61
|
+
def appsensor_event(dp, param, data)
|
62
|
+
TCellAgent::Instrumentation.safe_block("AppSensor Sending Event") {
|
63
|
+
event = TCellAgent::SensorEvents::TCellAppSensorEvent.new(
|
64
|
+
@uri,
|
65
|
+
dp,
|
66
|
+
@remote_addr,
|
67
|
+
param,
|
68
|
+
@route_id,
|
69
|
+
data=nil,
|
70
|
+
transaction_id=@transaction_id,
|
71
|
+
session_id=@session_id,
|
72
|
+
user_id=@user_id)
|
73
|
+
@sensor_triggered = true
|
74
|
+
TCellAgent.send_event(event)
|
75
|
+
}
|
76
|
+
end
|
77
|
+
def for_params
|
78
|
+
if @get_params
|
79
|
+
@get_params.each do |param_name, param_value|
|
80
|
+
if !param_value || !param_value.instance_of?(String) || param_value == ""
|
81
|
+
next
|
82
|
+
end
|
83
|
+
yield('get', param_name, param_value)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
if @post_params
|
87
|
+
@post_params.each do |param_name, param_value|
|
88
|
+
if !param_value || !param_value.instance_of?(String) || param_value == ""
|
89
|
+
next
|
90
|
+
end
|
91
|
+
yield('post', param_name, param_value)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def for_get_params
|
97
|
+
if @get_params
|
98
|
+
@get_params.each do |param_name, param_value|
|
99
|
+
if !param_value || !param_value.instance_of?(String) || param_value == ""
|
100
|
+
next
|
101
|
+
end
|
102
|
+
yield('get', param_name, param_value)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_response_size
|
108
|
+
if (@response_content_length && @response_content_length > TCellAgent::Policies::AppSensorPolicy::MAX_NORMAL_RESPONSE_BYTES)
|
109
|
+
appsensor_event(TCellAgent::Policies::AppSensorPolicy::DP_UNUSUAL_RESPONSE_SIZE, response_content_length.to_s, nil)
|
110
|
+
end
|
111
|
+
request_size = 0
|
112
|
+
if @request_body
|
113
|
+
if @request_body.kind_of?(StringIO)
|
114
|
+
request_size = @request_body.size
|
115
|
+
else
|
116
|
+
request_size = @request_content_length
|
117
|
+
end
|
118
|
+
end
|
119
|
+
if (request_size > TCellAgent::Policies::AppSensorPolicy::MAX_NORMAL_REQUEST_BYTES)
|
120
|
+
appsensor_event(TCellAgent::Policies::AppSensorPolicy::DP_UNUSUAL_REQUEST_SIZE,request_size.to_s, nil)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_response_code
|
125
|
+
@status_code = @status_code.to_i
|
126
|
+
if @status_code == 200
|
127
|
+
return
|
128
|
+
end
|
129
|
+
series = @status_code.to_i / 100
|
130
|
+
dp = nil
|
131
|
+
if (@status_code == 401)
|
132
|
+
dp = "s401"
|
133
|
+
elsif (@status_code == 403)
|
134
|
+
dp = "s403"
|
135
|
+
elsif (@status_code == 404)
|
136
|
+
dp = "s404"
|
137
|
+
elsif (series == 4)
|
138
|
+
dp = "s4xx"
|
139
|
+
elsif (@status_code == 500)
|
140
|
+
dp = "s500"
|
141
|
+
elsif (series == 5)
|
142
|
+
dp = "s5xx"
|
143
|
+
end
|
144
|
+
if (dp)
|
145
|
+
appsensor_event(dp, @status_code.to_s, nil)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def post_process
|
150
|
+
appsensor_policy = TCellAgent.policy(TCellAgent::PolicyTypes::AppSensor)
|
151
|
+
if (!appsensor_policy || !appsensor_policy.enabled)
|
152
|
+
return
|
153
|
+
end
|
154
|
+
|
155
|
+
@sensor_triggered = false;
|
156
|
+
|
157
|
+
if (appsensor_policy.option_enabled?("req_res_size"))
|
158
|
+
TCellAgent::Instrumentation.safe_block("AppSensor Testing Response Size") {
|
159
|
+
test_response_size
|
160
|
+
}
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
if (!@sensor_triggered && appsensor_policy.option_enabled?("resp_codes"))
|
165
|
+
TCellAgent::Instrumentation.safe_block("AppSensor Resting Response Code") {
|
166
|
+
test_response_code
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
170
|
+
if (!@sensor_triggered && appsensor_policy.option_enabled?("xss"))
|
171
|
+
TCellAgent::Instrumentation.safe_block("AppSensor Testing for XSS") {
|
172
|
+
for_params { | param_type, param_name, param_value |
|
173
|
+
if (TCellAgent::AppSensor.isXss(param_value))
|
174
|
+
appsensor_event("xss", param_name, nil)
|
175
|
+
return
|
176
|
+
end
|
177
|
+
}
|
178
|
+
}
|
179
|
+
end
|
180
|
+
|
181
|
+
if (!@sensor_triggered && appsensor_policy.option_enabled?("cmdi"))
|
182
|
+
TCellAgent::Instrumentation.safe_block("AppSensor Testing for CMDI") {
|
183
|
+
for_params { | param_type, param_name, param_value |
|
184
|
+
if (TCellAgent::AppSensor.isCmdi(param_value))
|
185
|
+
appsensor_event("cmdi", param_name, nil)
|
186
|
+
return
|
187
|
+
end
|
188
|
+
}
|
189
|
+
}
|
190
|
+
end
|
191
|
+
|
192
|
+
if (!@sensor_triggered && appsensor_policy.option_enabled?("sqli"))
|
193
|
+
TCellAgent::Instrumentation.safe_block("AppSensor Testing for SQLI") {
|
194
|
+
for_params { | param_type, param_name, param_value |
|
195
|
+
if (TCellAgent::AppSensor.isSqli(param_value))
|
196
|
+
appsensor_event("sqli", param_name, nil)
|
197
|
+
return
|
198
|
+
end
|
199
|
+
}
|
200
|
+
}
|
201
|
+
end
|
202
|
+
|
203
|
+
if (!@sensor_triggered && appsensor_policy.option_enabled?("retr"))
|
204
|
+
TCellAgent::Instrumentation.safe_block("AppSensor Testing for Return Chars") {
|
205
|
+
for_get_params { | param_type, param_name, param_value |
|
206
|
+
if (TCellAgent::AppSensor.containsReturnChars(param_value))
|
207
|
+
appsensor_event("retr", param_name, nil)
|
208
|
+
return
|
209
|
+
end
|
210
|
+
}
|
211
|
+
}
|
212
|
+
end
|
213
|
+
|
214
|
+
if (!@sensor_triggered && appsensor_policy.option_enabled?("null"))
|
215
|
+
TCellAgent::Instrumentation.safe_block("AppSensor Testing for Null") {
|
216
|
+
for_params { | param_type, param_name, param_value |
|
217
|
+
if (TCellAgent::AppSensor.containsNull(param_value))
|
218
|
+
appsensor_event("null", param_name, nil)
|
219
|
+
return
|
220
|
+
end
|
221
|
+
}
|
222
|
+
}
|
223
|
+
end
|
224
|
+
|
225
|
+
if (!@sensor_triggered && appsensor_policy.option_enabled?("null"))
|
226
|
+
TCellAgent::Instrumentation.safe_block("AppSensor Testing for File path traversal") {
|
227
|
+
for_params { | param_type, param_name, param_value |
|
228
|
+
if (TCellAgent::AppSensor.isPathTraversal(param_value))
|
229
|
+
appsensor_event("null", param_name, nil)
|
230
|
+
return
|
231
|
+
end
|
232
|
+
}
|
233
|
+
}
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|