tcell_agent 2.0.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/bin/tcell_agent +42 -146
  3. data/lib/tcell_agent.rb +8 -16
  4. data/lib/tcell_agent/agent.rb +76 -46
  5. data/lib/tcell_agent/config_initializer.rb +66 -0
  6. data/lib/tcell_agent/configuration.rb +72 -267
  7. data/lib/tcell_agent/instrument_servers.rb +14 -18
  8. data/lib/tcell_agent/instrumentation/cmdi.rb +15 -15
  9. data/lib/tcell_agent/instrumentation/lfi.rb +21 -10
  10. data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +20 -12
  11. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +45 -102
  12. data/lib/tcell_agent/logger.rb +1 -2
  13. data/lib/tcell_agent/policies/command_injection_policy.rb +1 -1
  14. data/lib/tcell_agent/rails/auth/authlogic.rb +49 -44
  15. data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
  16. data/lib/tcell_agent/rails/auth/devise.rb +103 -102
  17. data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
  18. data/lib/tcell_agent/rails/auth/doorkeeper.rb +54 -58
  19. data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
  20. data/lib/tcell_agent/rails/csrf_exception.rb +0 -8
  21. data/lib/tcell_agent/rails/dlp.rb +10 -8
  22. data/lib/tcell_agent/rails/middleware/global_middleware.rb +4 -1
  23. data/lib/tcell_agent/rails/{on_start.rb → railties/tcell_agent_railties.rb} +9 -16
  24. data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
  25. data/lib/tcell_agent/rails/routes.rb +6 -9
  26. data/lib/tcell_agent/rails/routes/grape.rb +4 -12
  27. data/lib/tcell_agent/rails/tcell_body_proxy.rb +0 -1
  28. data/lib/tcell_agent/rust/agent_config.rb +43 -32
  29. data/lib/tcell_agent/rust/{libtcellagent-4.14.0.dylib → libtcellagent-5.0.2.dylib} +0 -0
  30. data/lib/tcell_agent/rust/{libtcellagent-4.14.0.so → libtcellagent-5.0.2.so} +0 -0
  31. data/lib/tcell_agent/rust/{libtcellagent-alpine-4.14.0.so → libtcellagent-alpine-5.0.2.so} +0 -0
  32. data/lib/tcell_agent/rust/models.rb +9 -0
  33. data/lib/tcell_agent/rust/native_agent.rb +18 -0
  34. data/lib/tcell_agent/rust/native_library.rb +2 -1
  35. data/lib/tcell_agent/rust/{tcellagent-4.14.0.dll → tcellagent-5.0.2.dll} +0 -0
  36. data/lib/tcell_agent/servers/puma.rb +7 -7
  37. data/lib/tcell_agent/servers/rack_puma_handler.rb +23 -0
  38. data/lib/tcell_agent/servers/rails_server.rb +4 -4
  39. data/lib/tcell_agent/servers/unicorn.rb +1 -1
  40. data/lib/tcell_agent/servers/webrick.rb +0 -1
  41. data/lib/tcell_agent/settings_reporter.rb +0 -79
  42. data/lib/tcell_agent/tcell_context.rb +1 -1
  43. data/lib/tcell_agent/version.rb +1 -1
  44. data/spec/lib/tcell_agent/configuration_spec.rb +62 -212
  45. data/spec/lib/tcell_agent/instrument_servers_spec.rb +95 -0
  46. data/spec/lib/tcell_agent/{cmdi_spec.rb → instrumentation/cmdi_spec.rb} +50 -0
  47. data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +6 -0
  48. data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +19 -4
  49. data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +47 -2
  50. data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
  51. data/spec/lib/tcell_agent/settings_reporter_spec.rb +0 -73
  52. data/spec/spec_helper.rb +6 -0
  53. data/spec/support/builders.rb +6 -6
  54. data/spec/support/server_mocks/passenger_mock.rb +7 -0
  55. data/spec/support/server_mocks/puma_mock.rb +17 -0
  56. data/spec/support/server_mocks/rails_mock.rb +7 -0
  57. data/spec/support/server_mocks/thin_mock.rb +7 -0
  58. data/spec/support/server_mocks/unicorn_mock.rb +11 -0
  59. metadata +29 -16
  60. data/lib/tcell_agent/authlogic.rb +0 -23
  61. data/lib/tcell_agent/config/unknown_options.rb +0 -119
  62. data/lib/tcell_agent/devise.rb +0 -33
  63. data/lib/tcell_agent/rails/start_agent_after_initializers.rb +0 -12
  64. 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
- if TCellAgent.configuration.should_instrument_devise? && defined?(Devise)
2
- module TCellAgent
3
- require 'base64'
4
- require 'tcell_agent/agent'
5
-
6
- module DeviseInstrumentation
7
- module TCellFailureAppRespond
8
- def respond
9
- TCellAgent::Instrumentation.safe_block('Devise Failure App Respond') do
10
- if TCellAgent.configuration.should_intercept_requests?
11
- tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
12
- if tcell_data
13
- # in the case of http auth, user_id is set in
14
- # Devise::Strategies::Authenticatable.valid_for_http_auth?
15
- user_id = tcell_data.user_id
16
- user_id ||= _get_tcell_username
17
-
18
- # in the case of http auth, password is set in
19
- # Devise::Strategies::Authenticatable.valid_for_http_auth?
20
- password = tcell_data.password
21
- password ||= _get_tcell_password
22
-
23
- user_valid = nil
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
- )
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
- 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
49
- end
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
- 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']
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
- # prepend is ruby 2+ feature
67
- Devise::FailureApp.send(:prepend, DeviseInstrumentation::TCellFailureAppRespond)
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
- 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?
84
+ is_valid
85
+ end
73
86
 
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
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
- is_valid
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
- alias_method :tcell_validate, :validate
88
- def validate(resource, &block)
89
- is_valid = tcell_validate(resource, &block)
90
- send_event = is_valid
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
- TCellAgent::Instrumentation.safe_block('Devise Authenticatable Validate') do
100
- if send_event && TCellAgent.configuration.enabled &&
101
- TCellAgent.configuration.should_intercept_requests?
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
- is_valid
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
- if TCellAgent.configuration.should_instrument_doorkeeper? && defined?(Doorkeeper)
1
+ require 'tcell_agent/agent'
2
2
 
3
- require 'tcell_agent/agent'
4
- require 'tcell_agent/sensor_events/login_fraud'
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
- module TCellAgent
7
- module DoorkeeperInstrumentation
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::Instrumentation.safe_block('Doorkeeper Token Authorize') do
14
- return result unless TCellAgent.configuration.should_intercept_requests?
13
+ login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
14
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
15
15
 
16
- login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
17
- tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
16
+ return unless tcell_data
17
+ headers = request.env
18
18
 
19
- return unless tcell_data
20
- headers = request.env
21
-
22
- if result.is_a?(Doorkeeper::OAuth::TokenResponse)
23
- user_id = result.token.resource_owner_id
24
- login_policy.report_login_success(
25
- user_id,
26
- headers,
27
- tcell_data
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
- # prepend is ruby 2+ feature
76
- Doorkeeper::AuthorizationsController.send(:prepend, TCellAuthorizationsNew)
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
@@ -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
- tcell_data.sql_exceptions.push(
232
- { 'exception_name' => result.class.name, 'exception_payload' => message }
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 == 5
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)