tcell_agent 2.0.0 → 2.2.1
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/bin/tcell_agent +42 -146
- data/lib/tcell_agent.rb +8 -16
- data/lib/tcell_agent/agent.rb +76 -46
- data/lib/tcell_agent/config_initializer.rb +66 -0
- data/lib/tcell_agent/configuration.rb +72 -267
- data/lib/tcell_agent/instrument_servers.rb +14 -18
- data/lib/tcell_agent/instrumentation/cmdi.rb +15 -15
- data/lib/tcell_agent/instrumentation/lfi.rb +21 -10
- data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +20 -12
- data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +45 -102
- data/lib/tcell_agent/logger.rb +1 -2
- data/lib/tcell_agent/policies/command_injection_policy.rb +1 -1
- data/lib/tcell_agent/rails/auth/authlogic.rb +49 -44
- data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
- data/lib/tcell_agent/rails/auth/devise.rb +103 -102
- data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
- data/lib/tcell_agent/rails/auth/doorkeeper.rb +54 -58
- data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
- data/lib/tcell_agent/rails/csrf_exception.rb +0 -8
- data/lib/tcell_agent/rails/dlp.rb +10 -8
- data/lib/tcell_agent/rails/middleware/global_middleware.rb +4 -1
- data/lib/tcell_agent/rails/{on_start.rb → railties/tcell_agent_railties.rb} +9 -16
- data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
- data/lib/tcell_agent/rails/routes.rb +6 -9
- data/lib/tcell_agent/rails/routes/grape.rb +4 -12
- data/lib/tcell_agent/rails/tcell_body_proxy.rb +0 -1
- data/lib/tcell_agent/rust/agent_config.rb +43 -32
- data/lib/tcell_agent/rust/{libtcellagent-4.14.0.dylib → libtcellagent-5.0.2.dylib} +0 -0
- data/lib/tcell_agent/rust/{libtcellagent-4.14.0.so → libtcellagent-5.0.2.so} +0 -0
- data/lib/tcell_agent/rust/{libtcellagent-alpine-4.14.0.so → libtcellagent-alpine-5.0.2.so} +0 -0
- data/lib/tcell_agent/rust/models.rb +9 -0
- data/lib/tcell_agent/rust/native_agent.rb +18 -0
- data/lib/tcell_agent/rust/native_library.rb +2 -1
- data/lib/tcell_agent/rust/{tcellagent-4.14.0.dll → tcellagent-5.0.2.dll} +0 -0
- data/lib/tcell_agent/servers/puma.rb +7 -7
- data/lib/tcell_agent/servers/rack_puma_handler.rb +23 -0
- data/lib/tcell_agent/servers/rails_server.rb +4 -4
- data/lib/tcell_agent/servers/unicorn.rb +1 -1
- data/lib/tcell_agent/servers/webrick.rb +0 -1
- data/lib/tcell_agent/settings_reporter.rb +0 -79
- data/lib/tcell_agent/tcell_context.rb +1 -1
- data/lib/tcell_agent/version.rb +1 -1
- data/spec/lib/tcell_agent/configuration_spec.rb +62 -212
- data/spec/lib/tcell_agent/instrument_servers_spec.rb +95 -0
- data/spec/lib/tcell_agent/{cmdi_spec.rb → instrumentation/cmdi_spec.rb} +50 -0
- data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +6 -0
- data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +19 -4
- data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +47 -2
- data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
- data/spec/lib/tcell_agent/settings_reporter_spec.rb +0 -73
- data/spec/spec_helper.rb +6 -0
- data/spec/support/builders.rb +6 -6
- data/spec/support/server_mocks/passenger_mock.rb +7 -0
- data/spec/support/server_mocks/puma_mock.rb +17 -0
- data/spec/support/server_mocks/rails_mock.rb +7 -0
- data/spec/support/server_mocks/thin_mock.rb +7 -0
- data/spec/support/server_mocks/unicorn_mock.rb +11 -0
- metadata +29 -16
- data/lib/tcell_agent/authlogic.rb +0 -23
- data/lib/tcell_agent/config/unknown_options.rb +0 -119
- data/lib/tcell_agent/devise.rb +0 -33
- data/lib/tcell_agent/rails/start_agent_after_initializers.rb +0 -12
- data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -195
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'tcell_agent/rails/auth/userinfo'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
TCellAgent::UserInformation.class_eval do
|
5
|
+
class << self
|
6
|
+
alias_method :original_get_user_from_request, :get_user_from_request
|
7
|
+
def get_user_from_request(request)
|
8
|
+
orig_user_id = original_get_user_from_request(request)
|
9
|
+
begin
|
10
|
+
if request.session && request.session.key?('user_credentials_id')
|
11
|
+
return request.session['user_credentials_id'].to_s
|
12
|
+
end
|
13
|
+
rescue StandardError
|
14
|
+
return orig_user_id
|
15
|
+
end
|
16
|
+
orig_user_id
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,127 +1,128 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
module
|
7
|
-
|
8
|
-
|
9
|
-
TCellAgent
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
1
|
+
module TCellAgent
|
2
|
+
require 'base64'
|
3
|
+
require 'tcell_agent/agent'
|
4
|
+
|
5
|
+
module DeviseInstrumentation
|
6
|
+
module TCellFailureAppRespond
|
7
|
+
def respond
|
8
|
+
TCellAgent::Instrumentation.safe_block('Devise Failure App Respond') do
|
9
|
+
if TCellAgent.configuration.should_intercept_requests?
|
10
|
+
tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
|
11
|
+
if tcell_data
|
12
|
+
# in the case of http auth, user_id is set in
|
13
|
+
# Devise::Strategies::Authenticatable.valid_for_http_auth?
|
14
|
+
user_id = tcell_data.user_id
|
15
|
+
user_id ||= _get_tcell_username
|
16
|
+
|
17
|
+
# in the case of http auth, password is set in
|
18
|
+
# Devise::Strategies::Authenticatable.valid_for_http_auth?
|
19
|
+
password = tcell_data.password
|
20
|
+
password ||= _get_tcell_password
|
21
|
+
|
22
|
+
user_valid = warden_message != :not_found_in_database if defined?(warden_message)
|
23
|
+
|
24
|
+
login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
|
25
|
+
login_policy.report_login_failure(
|
26
|
+
user_id,
|
27
|
+
password,
|
28
|
+
request.env,
|
29
|
+
user_valid,
|
30
|
+
tcell_data
|
31
|
+
)
|
33
32
|
end
|
34
33
|
end
|
35
|
-
|
36
|
-
super if defined?(super)
|
37
34
|
end
|
38
35
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
36
|
+
super if defined?(super)
|
37
|
+
end
|
38
|
+
|
39
|
+
def _get_tcell_username
|
40
|
+
tcell_username = nil
|
41
|
+
TCellAgent::Instrumentation.safe_block('Devise Get TCell Username') do
|
42
|
+
keys = scope_class.authentication_keys.dup
|
43
|
+
user_params = request.POST.fetch('user', {})
|
44
|
+
keys.each do |key|
|
45
|
+
next_usename = user_params.fetch(key, nil)
|
46
|
+
if next_usename
|
47
|
+
tcell_username ||= ''
|
48
|
+
tcell_username += next_usename
|
50
49
|
end
|
51
50
|
end
|
52
|
-
tcell_username
|
53
51
|
end
|
52
|
+
tcell_username
|
53
|
+
end
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
tcell_password
|
55
|
+
def _get_tcell_password
|
56
|
+
tcell_password = nil
|
57
|
+
TCellAgent::Instrumentation.safe_block('Devise Get TCell Password') do
|
58
|
+
user_params = request.POST.fetch('user', {})
|
59
|
+
tcell_password = user_params['password']
|
62
60
|
end
|
61
|
+
tcell_password
|
63
62
|
end
|
64
63
|
end
|
64
|
+
end
|
65
65
|
|
66
|
-
|
67
|
-
|
66
|
+
# prepend is ruby 2+ feature
|
67
|
+
Devise::FailureApp.send(:prepend, DeviseInstrumentation::TCellFailureAppRespond)
|
68
|
+
|
69
|
+
Devise::Strategies::Authenticatable.class_eval do
|
70
|
+
alias_method :tcell_valid_for_http_auth?, :valid_for_http_auth?
|
71
|
+
def valid_for_http_auth?
|
72
|
+
is_valid = tcell_valid_for_http_auth?
|
73
|
+
|
74
|
+
TCellAgent::Instrumentation.safe_block('Devise set username for http basic auth') do
|
75
|
+
tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
|
76
|
+
if http_auth_hash && tcell_data
|
77
|
+
username = http_auth_hash[http_authentication_key]
|
78
|
+
password = http_auth_hash[:password]
|
79
|
+
tcell_data.user_id = username if username && !tcell_data.user_id
|
80
|
+
tcell_data.password = password if password && !tcell_data.password
|
81
|
+
end
|
82
|
+
end
|
68
83
|
|
69
|
-
|
70
|
-
|
71
|
-
def valid_for_http_auth?
|
72
|
-
is_valid = tcell_valid_for_http_auth?
|
84
|
+
is_valid
|
85
|
+
end
|
73
86
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
password = http_auth_hash[:password]
|
79
|
-
tcell_data.user_id = username if username && !tcell_data.user_id
|
80
|
-
tcell_data.password = password if password && !tcell_data.password
|
81
|
-
end
|
82
|
-
end
|
87
|
+
alias_method :tcell_validate, :validate
|
88
|
+
def validate(resource, &block)
|
89
|
+
is_valid = tcell_validate(resource, &block)
|
90
|
+
send_event = is_valid
|
83
91
|
|
84
|
-
|
92
|
+
# gets the first entry in the current backtrace
|
93
|
+
# syntax suggested by rubocop to improve performance
|
94
|
+
if caller(1..1).first.include? 'two_factor_authenticatable'
|
95
|
+
TCellAgent.logger.debug('Not sending login success event for Devise::Strategies::TwoFactorAuthenticatable since 2fa is unsupported', 'TCellAgent::DeviseInstrumentation')
|
96
|
+
send_event = false
|
85
97
|
end
|
86
98
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
# gets the first entry in the current backtrace
|
93
|
-
# syntax suggested by rubocop to improve performance
|
94
|
-
if caller(1..1).first.include? 'two_factor_authenticatable'
|
95
|
-
TCellAgent.logger.debug('Not sending login success event for Devise::Strategies::TwoFactorAuthenticatable since 2fa is unsupported', 'TCellAgent::DeviseInstrumentation')
|
96
|
-
send_event = false
|
97
|
-
end
|
99
|
+
TCellAgent::Instrumentation.safe_block('Devise Authenticatable Validate') do
|
100
|
+
if send_event && TCellAgent.configuration.should_intercept_requests?
|
101
|
+
username = nil
|
102
|
+
(authentication_keys || []).each do |auth_key|
|
103
|
+
attr = authentication_hash[auth_key] unless authentication_hash.nil?
|
98
104
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
username = nil
|
103
|
-
(authentication_keys || []).each do |auth_key|
|
104
|
-
attr = authentication_hash[auth_key]
|
105
|
-
if attr
|
106
|
-
username ||= ''
|
107
|
-
username += attr
|
108
|
-
end
|
105
|
+
if attr
|
106
|
+
username ||= ''
|
107
|
+
username += attr
|
109
108
|
end
|
110
|
-
|
111
|
-
tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
|
112
|
-
return is_valid unless tcell_data
|
113
|
-
|
114
|
-
login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
|
115
|
-
login_policy.report_login_success(
|
116
|
-
username,
|
117
|
-
request.env,
|
118
|
-
tcell_data
|
119
|
-
)
|
120
109
|
end
|
121
|
-
end
|
122
110
|
|
123
|
-
|
111
|
+
tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
|
112
|
+
return is_valid unless tcell_data
|
113
|
+
|
114
|
+
tcell_data.user_id = username if username && tcell_data.user_id.nil?
|
115
|
+
|
116
|
+
login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
|
117
|
+
login_policy.report_login_success(
|
118
|
+
username,
|
119
|
+
request.env,
|
120
|
+
tcell_data
|
121
|
+
)
|
122
|
+
end
|
124
123
|
end
|
124
|
+
|
125
|
+
is_valid
|
125
126
|
end
|
126
127
|
end
|
127
128
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'devise'
|
2
|
+
require 'devise/rails'
|
3
|
+
require 'devise/strategies/database_authenticatable'
|
4
|
+
require 'tcell_agent/rails/auth/userinfo'
|
5
|
+
|
6
|
+
module TCellAgent
|
7
|
+
TCellAgent::UserInformation.class_eval do
|
8
|
+
class << self
|
9
|
+
alias_method :original_get_user_from_request, :get_user_from_request
|
10
|
+
def get_user_from_request(request)
|
11
|
+
orig_user_id = original_get_user_from_request(request)
|
12
|
+
begin
|
13
|
+
if request.session && request.session.key?('warden.user.user.key')
|
14
|
+
userkey = request.session['warden.user.user.key']
|
15
|
+
user_id = if userkey.length == 2
|
16
|
+
userkey[0][0]
|
17
|
+
else
|
18
|
+
userkey[1][0]
|
19
|
+
end
|
20
|
+
return user_id.to_s if user_id.is_a? Integer
|
21
|
+
end
|
22
|
+
rescue StandardError
|
23
|
+
return orig_user_id
|
24
|
+
end
|
25
|
+
orig_user_id
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,65 +1,31 @@
|
|
1
|
-
|
1
|
+
require 'tcell_agent/agent'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
module TCellAgent
|
4
|
+
module DoorkeeperInstrumentation
|
5
|
+
Doorkeeper::TokensController.class_eval do
|
6
|
+
alias_method :tcell_authorize_response, :authorize_response
|
7
|
+
def authorize_response
|
8
|
+
result = tcell_authorize_response
|
5
9
|
|
6
|
-
|
7
|
-
|
8
|
-
Doorkeeper::TokensController.class_eval do
|
9
|
-
alias_method :tcell_authorize_response, :authorize_response
|
10
|
-
def authorize_response
|
11
|
-
result = tcell_authorize_response
|
10
|
+
TCellAgent::Instrumentation.safe_block('Doorkeeper Token Authorize') do
|
11
|
+
return result unless TCellAgent.configuration.should_intercept_requests?
|
12
12
|
|
13
|
-
TCellAgent
|
14
|
-
|
13
|
+
login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
|
14
|
+
tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
return unless tcell_data
|
17
|
+
headers = request.env
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
)
|
29
|
-
elsif result.is_a?(Doorkeeper::OAuth::ErrorResponse)
|
30
|
-
user_id = request.POST['client_id']
|
31
|
-
password = nil
|
32
|
-
user_valid = nil
|
33
|
-
login_policy.report_login_failure(
|
34
|
-
user_id,
|
35
|
-
password,
|
36
|
-
headers,
|
37
|
-
user_valid,
|
38
|
-
tcell_data
|
39
|
-
)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
result
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
module TCellAuthorizationsNew
|
48
|
-
def new
|
49
|
-
super if defined?(super)
|
50
|
-
|
51
|
-
TCellAgent::Instrumentation.safe_block('Doorkeeper Token Authorize') do
|
52
|
-
return unless TCellAgent.configuration.should_intercept_requests?
|
53
|
-
return unless pre_auth.error
|
54
|
-
|
55
|
-
login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
|
56
|
-
tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
|
57
|
-
|
58
|
-
return unless tcell_data
|
59
|
-
|
60
|
-
user_id = current_resource_owner.id
|
19
|
+
if result.is_a?(Doorkeeper::OAuth::TokenResponse)
|
20
|
+
user_id = result.token.resource_owner_id
|
21
|
+
login_policy.report_login_success(
|
22
|
+
user_id,
|
23
|
+
headers,
|
24
|
+
tcell_data
|
25
|
+
)
|
26
|
+
elsif result.is_a?(Doorkeeper::OAuth::ErrorResponse)
|
27
|
+
user_id = request.POST['client_id']
|
61
28
|
password = nil
|
62
|
-
headers = request.env
|
63
29
|
user_valid = nil
|
64
30
|
login_policy.report_login_failure(
|
65
31
|
user_id,
|
@@ -70,10 +36,40 @@ if TCellAgent.configuration.should_instrument_doorkeeper? && defined?(Doorkeeper
|
|
70
36
|
)
|
71
37
|
end
|
72
38
|
end
|
39
|
+
|
40
|
+
result
|
73
41
|
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module TCellAuthorizationsNew
|
45
|
+
def new
|
46
|
+
super if defined?(super)
|
47
|
+
|
48
|
+
TCellAgent::Instrumentation.safe_block('Doorkeeper Token Authorize') do
|
49
|
+
return unless TCellAgent.configuration.should_intercept_requests?
|
50
|
+
return unless pre_auth.error
|
74
51
|
|
75
|
-
|
76
|
-
|
52
|
+
login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
|
53
|
+
tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
|
54
|
+
|
55
|
+
return unless tcell_data
|
56
|
+
|
57
|
+
user_id = current_resource_owner.id
|
58
|
+
password = nil
|
59
|
+
headers = request.env
|
60
|
+
user_valid = nil
|
61
|
+
login_policy.report_login_failure(
|
62
|
+
user_id,
|
63
|
+
password,
|
64
|
+
headers,
|
65
|
+
user_valid,
|
66
|
+
tcell_data
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
77
70
|
end
|
71
|
+
|
72
|
+
# prepend is ruby 2+ feature
|
73
|
+
Doorkeeper::AuthorizationsController.send(:prepend, TCellAuthorizationsNew)
|
78
74
|
end
|
79
75
|
end
|
File without changes
|
@@ -16,12 +16,4 @@ module TCellAgent
|
|
16
16
|
super if defined?(super)
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
20
|
-
class MyRailtie < Rails::Railtie
|
21
|
-
initializer 'tcell.sensors' do |_app|
|
22
|
-
ActiveSupport.on_load :action_controller do
|
23
|
-
ActionController::Base.send(:include, TCellAgent::CsrfExceptionReporter)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
19
|
end
|
@@ -1,8 +1,5 @@
|
|
1
1
|
# See the file "LICENSE" for the full license governing this code.
|
2
2
|
|
3
|
-
require 'tcell_agent/authlogic' if defined?(Authlogic)
|
4
|
-
require 'tcell_agent/devise' if defined?(Devise)
|
5
|
-
|
6
3
|
require 'rails'
|
7
4
|
require 'uri'
|
8
5
|
require 'tcell_agent/agent'
|
@@ -21,7 +18,6 @@ require 'tcell_agent/rails/settings_reporter'
|
|
21
18
|
|
22
19
|
require 'tcell_agent/instrumentation'
|
23
20
|
|
24
|
-
require 'tcell_agent/userinfo'
|
25
21
|
require 'cgi'
|
26
22
|
require 'thread'
|
27
23
|
|
@@ -228,9 +224,15 @@ module TCellAgent
|
|
228
224
|
)
|
229
225
|
tcell_data = request_env[TCellAgent::Instrumentation::TCELL_ID]
|
230
226
|
if tcell_data && result.is_a?(ActiveRecord::StatementInvalid)
|
231
|
-
|
232
|
-
|
233
|
-
|
227
|
+
if message.is_a? Hash
|
228
|
+
tcell_data.sql_exceptions.push(
|
229
|
+
{ 'exception_name' => result.class.name, 'exception_payload' => message[:message] }
|
230
|
+
)
|
231
|
+
else
|
232
|
+
tcell_data.sql_exceptions.push(
|
233
|
+
{ 'exception_name' => result.class.name, 'exception_payload' => message }
|
234
|
+
)
|
235
|
+
end
|
234
236
|
end
|
235
237
|
end
|
236
238
|
end
|
@@ -253,7 +255,7 @@ module TCellAgent
|
|
253
255
|
end
|
254
256
|
|
255
257
|
ActiveRecord::Querying.module_eval do
|
256
|
-
if ::Rails::VERSION::MAJOR
|
258
|
+
if ::Rails::VERSION::MAJOR >= 5
|
257
259
|
alias_method :tcell_find_by_sql, :find_by_sql
|
258
260
|
def find_by_sql(*args)
|
259
261
|
results = tcell_find_by_sql(*args)
|