tcell_agent 0.4.0 → 1.0.0

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 (199) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +9 -22
  3. data/bin/tcell_agent +127 -132
  4. data/lib/tcell_agent/agent/event_processor.rb +23 -22
  5. data/lib/tcell_agent/agent/fork_pipe_manager.rb +7 -7
  6. data/lib/tcell_agent/agent/policy_manager.rb +20 -15
  7. data/lib/tcell_agent/agent/policy_types.rb +5 -11
  8. data/lib/tcell_agent/agent/static_agent.rb +5 -1
  9. data/lib/tcell_agent/agent.rb +6 -4
  10. data/lib/tcell_agent/api.rb +7 -9
  11. data/lib/tcell_agent/appsensor/meta_data.rb +11 -4
  12. data/lib/tcell_agent/authlogic.rb +3 -3
  13. data/lib/tcell_agent/cmdi.rb +6 -4
  14. data/lib/tcell_agent/config/unknown_options.rb +3 -1
  15. data/lib/tcell_agent/configuration.rb +47 -49
  16. data/lib/tcell_agent/devise.rb +2 -2
  17. data/lib/tcell_agent/hooks/login_fraud.rb +58 -29
  18. data/lib/tcell_agent/instrumentation.rb +11 -10
  19. data/lib/tcell_agent/logger.rb +2 -2
  20. data/lib/tcell_agent/patches/meta_data.rb +9 -13
  21. data/lib/tcell_agent/patches.rb +7 -10
  22. data/lib/tcell_agent/policies/clickjacking_policy.rb +4 -5
  23. data/lib/tcell_agent/policies/content_security_policy.rb +6 -12
  24. data/lib/tcell_agent/policies/dataloss_policy.rb +2 -2
  25. data/lib/tcell_agent/policies/http_redirect_policy.rb +2 -2
  26. data/lib/tcell_agent/policies/policy.rb +0 -2
  27. data/lib/tcell_agent/policies/rust_policies.rb +90 -0
  28. data/lib/tcell_agent/policies/secure_headers_policy.rb +2 -2
  29. data/lib/tcell_agent/rails/auth/authlogic.rb +42 -24
  30. data/lib/tcell_agent/rails/auth/devise.rb +44 -23
  31. data/lib/tcell_agent/rails/auth/doorkeeper.rb +33 -15
  32. data/lib/tcell_agent/rails/better_ip.rb +1 -1
  33. data/lib/tcell_agent/rails/csrf_exception.rb +2 -2
  34. data/lib/tcell_agent/rails/dlp/process_request.rb +1 -1
  35. data/lib/tcell_agent/rails/dlp.rb +6 -6
  36. data/lib/tcell_agent/rails/dlp_handler.rb +1 -1
  37. data/lib/tcell_agent/rails/js_agent_insert.rb +1 -1
  38. data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +1 -1
  39. data/lib/tcell_agent/rails/middleware/context_middleware.rb +3 -2
  40. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +10 -9
  41. data/lib/tcell_agent/rails/routes/grape.rb +6 -6
  42. data/lib/tcell_agent/rails/routes.rb +8 -11
  43. data/lib/tcell_agent/rust/libtcellagent-0.11.1.dylib +0 -0
  44. data/lib/tcell_agent/rust/{libtcellagent-0.6.1.so → libtcellagent-0.11.1.so} +0 -0
  45. data/lib/tcell_agent/rust/models.rb +16 -0
  46. data/lib/tcell_agent/rust/tcellagent-0.11.1.dll +0 -0
  47. data/lib/tcell_agent/rust/whisperer.rb +119 -48
  48. data/lib/tcell_agent/sensor_events/appsensor_meta_event.rb +17 -20
  49. data/lib/tcell_agent/sensor_events/command_injection.rb +50 -5
  50. data/lib/tcell_agent/sensor_events/login_fraud.rb +34 -18
  51. data/lib/tcell_agent/sensor_events/patches.rb +21 -0
  52. data/lib/tcell_agent/sensor_events/server_agent.rb +3 -3
  53. data/lib/tcell_agent/sensor_events/util/utils.rb +4 -3
  54. data/lib/tcell_agent/servers/puma.rb +2 -2
  55. data/lib/tcell_agent/servers/unicorn.rb +1 -1
  56. data/lib/tcell_agent/utils/passwords.rb +28 -0
  57. data/lib/tcell_agent/version.rb +1 -1
  58. data/lib/tcell_agent.rb +1 -5
  59. data/spec/apps/rails-3.2/config/tcell_agent.config +15 -0
  60. data/spec/apps/rails-3.2/log/development.log +0 -0
  61. data/spec/apps/rails-3.2/log/test.log +12 -0
  62. data/spec/apps/rails-4.1/log/test.log +0 -0
  63. data/spec/lib/tcell_agent/agent/fork_pipe_manager_spec.rb +46 -45
  64. data/spec/lib/tcell_agent/agent/policy_manager_spec.rb +276 -164
  65. data/spec/lib/tcell_agent/agent/static_agent_spec.rb +44 -47
  66. data/spec/lib/tcell_agent/api/api_spec.rb +16 -16
  67. data/spec/lib/tcell_agent/appsensor/injections_reporter_spec.rb +131 -116
  68. data/spec/lib/tcell_agent/appsensor/meta_data_spec.rb +55 -51
  69. data/spec/lib/tcell_agent/cmdi_spec.rb +413 -436
  70. data/spec/lib/tcell_agent/config/unknown_options_spec.rb +145 -128
  71. data/spec/lib/tcell_agent/configuration_spec.rb +165 -169
  72. data/spec/lib/tcell_agent/hooks/login_fraud_spec.rb +144 -153
  73. data/spec/lib/tcell_agent/instrumentation_spec.rb +84 -85
  74. data/spec/lib/tcell_agent/patches_spec.rb +70 -111
  75. data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +313 -244
  76. data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +28 -28
  77. data/spec/lib/tcell_agent/policies/command_injection_policy_spec.rb +643 -513
  78. data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +55 -102
  79. data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +111 -134
  80. data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +141 -146
  81. data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +8 -8
  82. data/spec/lib/tcell_agent/policies/login_policy_spec.rb +15 -17
  83. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +231 -559
  84. data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +27 -27
  85. data/spec/lib/tcell_agent/rails/better_ip_spec.rb +30 -34
  86. data/spec/lib/tcell_agent/rails/logger_spec.rb +50 -49
  87. data/spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb +182 -199
  88. data/spec/lib/tcell_agent/rails/middleware/dlp_middleware_spec.rb +110 -84
  89. data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +107 -85
  90. data/spec/lib/tcell_agent/rails/middleware/redirect_middleware_spec.rb +68 -40
  91. data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +81 -67
  92. data/spec/lib/tcell_agent/rails/responses_spec.rb +33 -37
  93. data/spec/lib/tcell_agent/rails/routes/grape_spec.rb +116 -121
  94. data/spec/lib/tcell_agent/rails/routes/route_id_spec.rb +25 -28
  95. data/spec/lib/tcell_agent/rails/routes/routes_spec.rb +87 -85
  96. data/spec/lib/tcell_agent/rails_spec.rb +1 -6
  97. data/spec/lib/tcell_agent/rust/models_spec.rb +112 -0
  98. data/spec/lib/tcell_agent/rust/whisperer_spec.rb +502 -179
  99. data/spec/lib/tcell_agent/sensor_events/appsensor_meta_event_spec.rb +44 -33
  100. data/spec/lib/tcell_agent/sensor_events/dlp_spec.rb +4 -4
  101. data/spec/lib/tcell_agent/sensor_events/sessions_metric_spec.rb +183 -169
  102. data/spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb +25 -25
  103. data/spec/lib/tcell_agent/utils/bounded_queue_spec.rb +17 -20
  104. data/spec/lib/tcell_agent/utils/params_spec.rb +28 -28
  105. data/spec/lib/tcell_agent/utils/passwords_spec.rb +143 -0
  106. data/spec/lib/tcell_agent/utils/strings_spec.rb +35 -35
  107. data/spec/lib/tcell_agent_spec.rb +8 -8
  108. data/spec/spec_helper.rb +4 -4
  109. data/spec/support/middleware_helper.rb +10 -10
  110. data/spec/support/static_agent_overrides.rb +16 -12
  111. data/tcell_agent.gemspec +17 -33
  112. metadata +43 -198
  113. data/LICENSE_libinjection +0 -32
  114. data/Readme.txt +0 -7
  115. data/ext/libinjection/extconf.rb +0 -3
  116. data/ext/libinjection/libinjection.h +0 -65
  117. data/ext/libinjection/libinjection_html5.c +0 -847
  118. data/ext/libinjection/libinjection_html5.h +0 -54
  119. data/ext/libinjection/libinjection_sqli.c +0 -2317
  120. data/ext/libinjection/libinjection_sqli.h +0 -295
  121. data/ext/libinjection/libinjection_sqli_data.h +0 -9004
  122. data/ext/libinjection/libinjection_wrap.c +0 -3525
  123. data/ext/libinjection/libinjection_xss.c +0 -531
  124. data/ext/libinjection/libinjection_xss.h +0 -21
  125. data/lib/tcell_agent/appsensor/injections_matcher.rb +0 -155
  126. data/lib/tcell_agent/appsensor/rules/appsensor_rule_manager.rb +0 -49
  127. data/lib/tcell_agent/appsensor/rules/appsensor_rule_set.rb +0 -67
  128. data/lib/tcell_agent/appsensor/rules/baserules.json +0 -467
  129. data/lib/tcell_agent/patches/block_rule.rb +0 -93
  130. data/lib/tcell_agent/patches/sensors_matcher.rb +0 -31
  131. data/lib/tcell_agent/policies/appsensor/cmdi_sensor.rb +0 -23
  132. data/lib/tcell_agent/policies/appsensor/fpt_sensor.rb +0 -23
  133. data/lib/tcell_agent/policies/appsensor/injection_sensor.rb +0 -117
  134. data/lib/tcell_agent/policies/appsensor/nullbyte_sensor.rb +0 -26
  135. data/lib/tcell_agent/policies/appsensor/retr_sensor.rb +0 -22
  136. data/lib/tcell_agent/policies/appsensor/sqli_sensor.rb +0 -34
  137. data/lib/tcell_agent/policies/appsensor/xss_sensor.rb +0 -34
  138. data/lib/tcell_agent/policies/appsensor_policy.rb +0 -49
  139. data/lib/tcell_agent/policies/command_injection_policy.rb +0 -196
  140. data/lib/tcell_agent/policies/honeytokens_policy.rb +0 -69
  141. data/lib/tcell_agent/policies/patches_policy.rb +0 -84
  142. data/lib/tcell_agent/rust/libtcellagent-0.6.1.dylib +0 -0
  143. data/lib/tcell_agent/rust/tcellagent-0.6.1.dll +0 -0
  144. data/spec/apps/rails-3.2/Gemfile +0 -25
  145. data/spec/apps/rails-3.2/Gemfile.lock +0 -126
  146. data/spec/apps/rails-3.2/Rakefile +0 -7
  147. data/spec/apps/rails-3.2/app/assets/images/rails.png +0 -0
  148. data/spec/apps/rails-3.2/app/assets/javascripts/application.js +0 -15
  149. data/spec/apps/rails-3.2/app/assets/stylesheets/application.css +0 -13
  150. data/spec/apps/rails-3.2/app/controllers/application_controller.rb +0 -3
  151. data/spec/apps/rails-3.2/app/controllers/t_cell_app_controller.rb +0 -5
  152. data/spec/apps/rails-3.2/app/helpers/application_helper.rb +0 -2
  153. data/spec/apps/rails-3.2/app/views/layouts/application.html.erb +0 -14
  154. data/spec/apps/rails-3.2/app/views/t_cell_app/index.html.erb +0 -1
  155. data/spec/apps/rails-3.2/config/application.rb +0 -63
  156. data/spec/apps/rails-3.2/config/boot.rb +0 -6
  157. data/spec/apps/rails-3.2/config/environment.rb +0 -5
  158. data/spec/apps/rails-3.2/config/environments/test.rb +0 -37
  159. data/spec/apps/rails-3.2/config/routes.rb +0 -11
  160. data/spec/apps/rails-3.2/config.ru +0 -4
  161. data/spec/apps/rails-4.1/Gemfile +0 -7
  162. data/spec/apps/rails-4.1/Gemfile.lock +0 -114
  163. data/spec/apps/rails-4.1/Rakefile +0 -6
  164. data/spec/apps/rails-4.1/app/assets/javascripts/application.js +0 -16
  165. data/spec/apps/rails-4.1/app/assets/stylesheets/application.css +0 -15
  166. data/spec/apps/rails-4.1/app/controllers/application_controller.rb +0 -5
  167. data/spec/apps/rails-4.1/app/controllers/t_cell_app_controller.rb +0 -5
  168. data/spec/apps/rails-4.1/app/helpers/application_helper.rb +0 -2
  169. data/spec/apps/rails-4.1/app/views/layouts/application.html.erb +0 -14
  170. data/spec/apps/rails-4.1/app/views/t_cell_app/index.html.erb +0 -1
  171. data/spec/apps/rails-4.1/config/application.rb +0 -24
  172. data/spec/apps/rails-4.1/config/boot.rb +0 -4
  173. data/spec/apps/rails-4.1/config/environment.rb +0 -5
  174. data/spec/apps/rails-4.1/config/environments/test.rb +0 -41
  175. data/spec/apps/rails-4.1/config/initializers/assets.rb +0 -8
  176. data/spec/apps/rails-4.1/config/initializers/backtrace_silencers.rb +0 -7
  177. data/spec/apps/rails-4.1/config/initializers/cookies_serializer.rb +0 -3
  178. data/spec/apps/rails-4.1/config/initializers/filter_parameter_logging.rb +0 -4
  179. data/spec/apps/rails-4.1/config/initializers/inflections.rb +0 -16
  180. data/spec/apps/rails-4.1/config/initializers/mime_types.rb +0 -4
  181. data/spec/apps/rails-4.1/config/initializers/session_store.rb +0 -3
  182. data/spec/apps/rails-4.1/config/initializers/wrap_parameters.rb +0 -14
  183. data/spec/apps/rails-4.1/config/locales/en.yml +0 -23
  184. data/spec/apps/rails-4.1/config/routes.rb +0 -12
  185. data/spec/apps/rails-4.1/config/secrets.yml +0 -22
  186. data/spec/apps/rails-4.1/config.ru +0 -4
  187. data/spec/controllers/application_controller.rb +0 -12
  188. data/spec/lib/tcell_agent/appsensor/injections_matcher_spec.rb +0 -522
  189. data/spec/lib/tcell_agent/appsensor/rules/appsensor_rule_manager_spec.rb +0 -23
  190. data/spec/lib/tcell_agent/appsensor/rules/appsensor_rule_set_spec.rb +0 -159
  191. data/spec/lib/tcell_agent/patches/block_rule_spec.rb +0 -458
  192. data/spec/lib/tcell_agent/patches/sensors_matcher_spec.rb +0 -35
  193. data/spec/lib/tcell_agent/policies/appsensor/cmdi_sensor_spec.rb +0 -139
  194. data/spec/lib/tcell_agent/policies/appsensor/fpt_sensor_spec.rb +0 -139
  195. data/spec/lib/tcell_agent/policies/appsensor/nullbyte_sensor_spec.rb +0 -167
  196. data/spec/lib/tcell_agent/policies/appsensor/retr_sensor_spec.rb +0 -139
  197. data/spec/lib/tcell_agent/policies/appsensor/sqli_sensor_spec.rb +0 -246
  198. data/spec/lib/tcell_agent/policies/appsensor/xss_sensor_spec.rb +0 -882
  199. data/spec/lib/tcell_agent/policies/honeytokens_policy_spec.rb +0 -22
@@ -1,3 +1,4 @@
1
+ require 'tcell_agent/rust/models'
1
2
  require 'tcell_agent/logger'
2
3
 
3
4
 
@@ -8,23 +9,48 @@ module TCellAgent
8
9
  module Wrapper
9
10
  extend FFI::Library
10
11
 
11
- begin
12
- VERSION = "0.6.1"
13
- prefix = "lib"
14
- extension = ".so"
15
- if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
16
- extension = ".dll"
17
- prefix = ""
18
- elsif /darwin/ =~ RUBY_PLATFORM
19
- extension = ".dylib"
20
- end
12
+ VERSION = "0.11.1"
13
+ prefix = "lib"
14
+ extension = ".so"
15
+ if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
16
+ extension = ".dll"
17
+ prefix = ""
18
+ elsif /darwin/ =~ RUBY_PLATFORM
19
+ extension = ".dylib"
20
+ end
21
21
 
22
+ begin
22
23
  ffi_lib File.join(File.dirname(__FILE__), "#{prefix}tcellagent-#{VERSION}#{extension}")
23
- attach_function :cmdi_parse_sh, [:pointer, :size_t, :pointer, :size_t], :int
24
24
 
25
- attach_function :appfirewall_policy_init, [:pointer, :size_t, :pointer, :size_t, :pointer, :size_t], :int
26
- attach_function :appfirewall_policy_apply, [:pointer, :pointer, :size_t, :pointer, :size_t], :int
27
- attach_function :appfirewall_free, [:pointer], :void
25
+ # result [int]: 0+ length of buffer_out answer
26
+ # -1 general error
27
+ # -2 buffer_out is not big enough for response
28
+ # -3 buffer_out is null
29
+ attach_function :create_agent, [:pointer, :size_t, :pointer, :size_t], :int
30
+
31
+ # result [int]: 0+ length of buffer_out answer
32
+ # -1 general error
33
+ # -2 buffer_out is not big enough for response
34
+ # -3 buffer_out is null
35
+ attach_function :update_policies, [:pointer, :pointer, :size_t, :pointer, :size_t], :int
36
+
37
+ # result [int]: 0+ length of buffer_out answer
38
+ # -1 general error
39
+ # -2 buffer_out is not big enough for response
40
+ # -3 buffer_out is null
41
+ attach_function :appfirewall_apply, [:pointer, :pointer, :size_t, :pointer, :size_t], :int
42
+
43
+ # result [int]: 0+ length of buffer_out answer
44
+ # -1 general error
45
+ # -2 buffer_out is not big enough for response
46
+ # -3 buffer_out is null
47
+ attach_function :patches_apply, [:pointer, :pointer, :size_t, :pointer, :size_t], :int
48
+
49
+ # result [int]: 0+ length of buffer_out answer
50
+ # -1 general error
51
+ # -2 buffer_out is not big enough for response
52
+ # -3 buffer_out is null
53
+ attach_function :cmdi_apply, [:pointer, :pointer, :size_t, :pointer, :size_t], :int
28
54
 
29
55
  def self.common_lib_available?
30
56
  true
@@ -41,71 +67,116 @@ module TCellAgent
41
67
  end
42
68
 
43
69
  module Whisperer
44
- def self.convert_result(result_size, result)
45
- begin
46
- return JSON.parse(result.get_string(0, result_size)) if result_size >= 0
47
- rescue JSON::ParserError
48
- # don't log the actual error since it might contain payload information
49
- TCellAgent.logger.error("JSON::ParserError ocurred when trying to parse native lib response")
70
+ def self.convert_result(function_called, result_size, result)
71
+ if result_size < 0
72
+ TCellAgent.logger.error(
73
+ "Error response from `#{function_called}` in native library: #{result_size}"
74
+ )
75
+ else
76
+ begin
77
+ return JSON.parse(result.get_string(0, result_size))
78
+ rescue JSON::ParserError
79
+ # don't log the actual error since it might contain payload information
80
+ TCellAgent.logger.error(
81
+ "Could not parse json response from `#{function_called}` in native library."
82
+ )
83
+ end
50
84
  end
51
85
 
52
86
  return {}
53
87
  end
54
88
 
55
- def self.parse_cmd(cmd)
56
- if TCellAgent::Rust::Wrapper.common_lib_available? &&
57
- TCellAgent::Utils::Strings.present?(cmd)
58
- cmd_pointer = FFI::MemoryPointer.from_string(cmd)
89
+ def self.create_agent()
90
+ if TCellAgent::Rust::Wrapper.common_lib_available?
91
+ agent_config = {
92
+ "appfirewall" => {
93
+ "enable_body_xxe_inspection" => false,
94
+ "enable_body_json_inspection" => false,
95
+ "allow_send_payloads" => TCellAgent.configuration.allow_payloads,
96
+ "allow_log_payloads" => true
97
+ }
98
+ }
99
+ config_pointer = FFI::MemoryPointer.from_string(JSON.dump(agent_config))
59
100
 
60
101
  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
61
-
62
- # cmd_pointer.size - 1: strips null terminator
63
- result_size = TCellAgent::Rust::Wrapper.cmdi_parse_sh(cmd_pointer, cmd_pointer.size - 1, buf, buf.size)
64
- return self.convert_result(result_size, buf)
102
+ # config_pointer.size - 1: strips null terminator
103
+ result_size = TCellAgent::Rust::Wrapper.create_agent(
104
+ config_pointer, config_pointer.size - 1, buf, buf.size
105
+ )
106
+ return self.convert_result("create_agent", result_size, buf)
65
107
  end
66
108
 
67
109
  return {}
68
110
  end
69
111
 
70
- def self.init_appfirewall(policy, allow_payloads)
71
- if TCellAgent::Rust::Wrapper.common_lib_available? && policy
72
- policy_pointer = FFI::MemoryPointer.from_string(JSON.dump(policy))
73
- config_pointer = FFI::MemoryPointer.from_string(JSON.dump({"allow_send_payloads" => allow_payloads}))
112
+ def self.update_policies(agent_ptr, policies)
113
+ if TCellAgent::Rust::Wrapper.common_lib_available? &&
114
+ agent_ptr &&
115
+ TCellAgent::Utils::Strings.present?(policies)
116
+ policies_pointer = FFI::MemoryPointer.from_string(JSON.dump(policies))
74
117
 
75
118
  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
76
- # policy_pointer.size - 1: strips null terminator
77
- # config_pointer.size - 1: strips null terminator
78
- result_size = TCellAgent::Rust::Wrapper.appfirewall_policy_init(
79
- policy_pointer, policy_pointer.size - 1, config_pointer, config_pointer.size - 1, buf, buf.size
119
+ # policies_pointer.size - 1: strips null terminator
120
+ result_size = TCellAgent::Rust::Wrapper.update_policies(
121
+ FFI::Pointer.new(agent_ptr), policies_pointer, policies_pointer.size - 1, buf, buf.size
80
122
  )
81
- return self.convert_result(result_size, buf)
123
+ return self.convert_result("update_policies", result_size, buf)
82
124
  end
83
125
 
84
126
  return {}
85
127
  end
86
128
 
87
- def self.apply_appfirewall(appfirewall_ptr, request_response_json)
129
+ def self.apply_appfirewall(agent_ptr, appsensor_meta)
130
+ if TCellAgent::Rust::Wrapper.common_lib_available? &&
131
+ agent_ptr &&
132
+ appsensor_meta
133
+ request_response_json = TCellAgent::Rust::Models.create_request_response(appsensor_meta)
134
+ request_response_pointer = FFI::MemoryPointer.from_string(JSON.dump(request_response_json))
135
+
136
+ buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
137
+ # request_response_pointer.size - 1: strips null terminator
138
+ result_size = TCellAgent::Rust::Wrapper.appfirewall_apply(
139
+ FFI::Pointer.new(agent_ptr), request_response_pointer, request_response_pointer.size - 1, buf, buf.size
140
+ )
141
+ return self.convert_result("apply_appfirewall", result_size, buf)
142
+ end
143
+
144
+ return {}
145
+ end
146
+
147
+ def self.apply_patches(agent_ptr, appsensor_meta)
88
148
  if TCellAgent::Rust::Wrapper.common_lib_available? &&
89
- request_response_json &&
90
- !appfirewall_ptr.nil?
91
- request_response_pointer = FFI::MemoryPointer.from_string(JSON.dump(request_response_json))
149
+ agent_ptr &&
150
+ appsensor_meta
151
+ patches_request_json = TCellAgent::Rust::Models.create_patches_request(appsensor_meta)
152
+ patches_request_pointer = FFI::MemoryPointer.from_string(JSON.dump(patches_request_json))
92
153
 
93
154
  buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
94
- # request_response_pointer.size - 1: strips null terminator
95
- result_size = TCellAgent::Rust::Wrapper.appfirewall_policy_apply(
96
- FFI::Pointer.new(appfirewall_ptr), request_response_pointer, request_response_pointer.size - 1, buf, buf.size
155
+ # patches_request_pointer.size - 1: strips null terminator
156
+ result_size = TCellAgent::Rust::Wrapper.patches_apply(
157
+ FFI::Pointer.new(agent_ptr), patches_request_pointer, patches_request_pointer.size - 1, buf, buf.size
97
158
  )
98
- return self.convert_result(result_size, buf)
159
+ return self.convert_result("apply_patches", result_size, buf)
99
160
  end
100
161
 
101
162
  return {}
102
163
  end
103
164
 
165
+ def self.apply_cmdi(agent_ptr, command)
166
+ if TCellAgent::Rust::Wrapper.common_lib_available? &&
167
+ agent_ptr &&
168
+ TCellAgent::Utils::Strings.present?(command)
169
+ command_pointer = FFI::MemoryPointer.from_string(command)
104
170
 
105
- def self.free_appfirewall(appfirewall_ptr)
106
- if TCellAgent::Rust::Wrapper.common_lib_available? && !appfirewall_ptr.nil?
107
- TCellAgent::Rust::Wrapper.appfirewall_free(FFI::Pointer.new(appfirewall_ptr))
171
+ buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
172
+ # patches_request_pointer.size - 1: strips null terminator
173
+ result_size = TCellAgent::Rust::Wrapper.cmdi_apply(
174
+ FFI::Pointer.new(agent_ptr), command_pointer, command_pointer.size - 1, buf, buf.size
175
+ )
176
+ return self.convert_result("apply_cmdi", result_size, buf)
108
177
  end
178
+
179
+ return {}
109
180
  end
110
181
  end
111
182
  end
@@ -6,7 +6,6 @@ require 'tcell_agent/sensor_events/sensor'
6
6
  require 'tcell_agent/agent'
7
7
  require 'tcell_agent/agent/policy_types'
8
8
  require 'tcell_agent/appsensor/meta_data'
9
- require 'tcell_agent/policies/appsensor_policy'
10
9
  require 'tcell_agent/utils/params'
11
10
 
12
11
 
@@ -23,21 +22,22 @@ module TCellAgent
23
22
  def build(request, response_content_length, response_code, response_headers)
24
23
  tcell_context = request.env[TCellAgent::Instrumentation::TCELL_ID]
25
24
  meta_event = AppSensorMetaEvent.new(
26
- request.request_method,
27
- TCellAgent::Utils::Rails.better_ip(request),
25
+ tcell_context.request_method,
26
+ tcell_context.ip_address,
28
27
  tcell_context.route_id,
29
28
  tcell_context.hmac_session_id,
30
29
  tcell_context.user_id,
31
- tcell_context.transaction_id
30
+ tcell_context.transaction_id,
31
+ tcell_context.uri
32
32
  )
33
33
 
34
34
  meta_event.csrf_exception_name = tcell_context.csrf_exception_name
35
- meta_event.user_agent = request.env['HTTP_USER_AGENT']
35
+ meta_event.user_agent = tcell_context.user_agent
36
36
  meta_event.request_content_bytes_len = (request.content_length || 0).to_i
37
37
  meta_event.response_content_bytes_len = response_content_length
38
38
 
39
- meta_event.location = "#{request.base_url}#{request.fullpath}"
40
- meta_event.path = request.path
39
+ meta_event.location = tcell_context.uri
40
+ meta_event.path = tcell_context.path
41
41
 
42
42
  meta_event.get_dict = request.GET
43
43
  meta_event.cookie_dict = request.cookies
@@ -46,7 +46,7 @@ module TCellAgent
46
46
  # don't enqueue parameter values of unknown type to avoid any serialization issues
47
47
  meta_event.post_dict = TCellAgent::Utils::Params.flatten(request.POST)
48
48
 
49
- meta_event.path_parameters = request.env[TCellAgent::Instrumentation::TCELL_ID].path_parameters
49
+ meta_event.path_parameters = tcell_context.path_parameters
50
50
  meta_event.response_code = response_code
51
51
  meta_event.response_headers = response_headers
52
52
 
@@ -68,28 +68,25 @@ module TCellAgent
68
68
  end
69
69
 
70
70
  def build_basic(appsensor_meta)
71
- meta_event = AppSensorMetaEvent.new(
71
+ AppSensorMetaEvent.new(
72
72
  appsensor_meta.method,
73
73
  appsensor_meta.remote_address,
74
74
  appsensor_meta.route_id,
75
75
  appsensor_meta.session_id,
76
76
  appsensor_meta.user_id,
77
- appsensor_meta.transaction_id
77
+ appsensor_meta.transaction_id,
78
+ appsensor_meta.location
78
79
  )
79
-
80
- meta_event.location = appsensor_meta.location
81
-
82
- meta_event
83
80
  end
84
81
  end
85
82
 
86
83
 
87
- attr_accessor :location, :request_content_bytes_len, :response_content_bytes_len,
84
+ attr_accessor :request_content_bytes_len, :response_content_bytes_len,
88
85
  :response_code, :user_agent, :response_headers, :csrf_exception_name, :path,
89
86
  :sql_exceptions, :database_result_sizes
90
87
 
91
- def initialize(method, remote_address, route_id, session_id, user_id, transaction_id)
92
- super(method, remote_address, route_id, session_id, user_id, transaction_id)
88
+ def initialize(method, remote_address, route_id, session_id, user_id, transaction_id, location)
89
+ super(method, remote_address, route_id, session_id, user_id, transaction_id, location)
93
90
 
94
91
  @request_content_bytes_len = 0
95
92
  @response_content_bytes_len = 0
@@ -97,10 +94,10 @@ module TCellAgent
97
94
  end
98
95
 
99
96
  def post_process
100
- appsensor_policy = TCellAgent.policy(TCellAgent::PolicyTypes::AppSensor)
101
- return unless appsensor_policy
97
+ rust_policies = TCellAgent.policy(TCellAgent::PolicyTypes::Rust)
98
+ return unless rust_policies
102
99
 
103
- appsensor_policy.process_meta_event(self)
100
+ rust_policies.check_appfirewall_injections(self)
104
101
  end
105
102
 
106
103
  def flattened_post_dict
@@ -13,6 +13,46 @@ module TCellAgent
13
13
  end
14
14
 
15
15
  class CommandInjectionEvent < TCellSensorEvent
16
+
17
+ def self.build_from_native_lib_response_and_tcell_context(apply_response,
18
+ tcell_context)
19
+ matches = apply_response.fetch("matches", [])
20
+
21
+ if matches && matches.size > 0
22
+ method, remote_address, route_id, session_id, user_id, uri = nil
23
+ if tcell_context
24
+ method = tcell_context.request_method
25
+ remote_address = tcell_context.ip_address
26
+ route_id = tcell_context.route_id
27
+ session_id = tcell_context.hmac_session_id
28
+ user_id = tcell_context.user_id
29
+ uri = tcell_context.uri
30
+ end
31
+
32
+ matches_without_emtpy_values = matches.map do |match|
33
+ CommandInjectionMatchEvent.new(
34
+ match["rule_id"], match["command"]
35
+ )
36
+ end
37
+
38
+ CommandInjectionEvent.new(
39
+ apply_response["commands"],
40
+ blocked=apply_response.fetch("blocked", false),
41
+ matches=matches_without_emtpy_values,
42
+ method=method,
43
+ remote_address=remote_address,
44
+ route_id=route_id,
45
+ session_id=session_id,
46
+ user_id=user_id,
47
+ uri=uri,
48
+ full_commandline=apply_response["full_commandline"])
49
+
50
+ else
51
+ nil
52
+ end
53
+ end
54
+
55
+
16
56
  def initialize(commands,
17
57
  blocked,
18
58
  matches,
@@ -21,6 +61,7 @@ module TCellAgent
21
61
  route_id=nil,
22
62
  session_id=nil,
23
63
  user_id=nil,
64
+ uri=nil,
24
65
  full_commandline=nil)
25
66
  super("cmdi")
26
67
 
@@ -29,28 +70,32 @@ module TCellAgent
29
70
  self["matches"] = matches
30
71
 
31
72
  if method
32
- self["method"] = method
73
+ self["m"] = method
33
74
  end
34
75
 
35
76
  if remote_address
36
- self["remote_address"] = remote_address
77
+ self["remote_addr"] = remote_address
37
78
  end
38
79
 
39
80
  if route_id
40
- self["route_id"] = route_id
81
+ self["rid"] = route_id
41
82
  end
42
83
 
43
84
  if session_id
44
- self["session_id"] = session_id
85
+ self["sid"] = session_id
45
86
  end
46
87
 
47
88
  if user_id
48
- self["user_id"] = user_id
89
+ self["uid"] = user_id
49
90
  end
50
91
 
51
92
  if full_commandline
52
93
  self["full_commandline"] = full_commandline
53
94
  end
95
+
96
+ if uri
97
+ self["uri"] = TCellAgent::SensorEvents::Util.strip_uri_values(uri)
98
+ end
54
99
  end
55
100
  end
56
101
 
@@ -5,39 +5,55 @@ require 'tcell_agent/sensor_events/sensor'
5
5
 
6
6
  module TCellAgent
7
7
  module SensorEvents
8
-
9
8
  class LoginEvent < TCellSensorEvent
10
- def initialize(header_keys, tcell_data, user_id, user_valid)
11
- super("login")
12
-
13
- self["header_keys"] = header_keys
14
-
15
- self["user_agent"] = tcell_data.user_agent.to_s if tcell_data.user_agent
16
- self["referrer"] = TCellAgent::SensorEvents::Util.strip_uri_values(tcell_data.referrer) if tcell_data.referrer
17
- self["remote_addr"] = tcell_data.ip_address.to_s if tcell_data.ip_address
18
- self["user_id"] = user_id.to_s if user_id
19
- self["document_uri"] = TCellAgent::SensorEvents::Util.strip_uri_values(tcell_data.path) if tcell_data.path
20
- self["session"] = tcell_data.hmac_session_id if tcell_data.hmac_session_id
9
+ def initialize(header_keys,
10
+ tcell_data,
11
+ user_id,
12
+ password,
13
+ user_valid)
14
+ super('login')
15
+
16
+ self['header_keys'] = header_keys
17
+
18
+ self['user_agent'] = tcell_data.user_agent.to_s if tcell_data.user_agent
19
+ self['referrer'] = TCellAgent::SensorEvents::Util.strip_uri_values(tcell_data.referrer) if tcell_data.referrer
20
+ self['remote_addr'] = tcell_data.ip_address.to_s if tcell_data.ip_address
21
+ self['user_id'] = user_id.to_s if user_id
22
+ self['document_uri'] = TCellAgent::SensorEvents::Util.strip_uri_values(tcell_data.path) if tcell_data.path
23
+ self['session'] = tcell_data.hmac_session_id if tcell_data.hmac_session_id
24
+
25
+ digest = TCellAgent::Utils::Passwords.fingerprint_password(password,
26
+ user_id)
27
+ self['password_id'] = digest if digest
28
+ self['user_valid'] = user_valid if user_valid
21
29
  end
22
30
  end
23
31
 
24
32
  class LoginFailure < LoginEvent
25
- def initialize(request_env_or_header_keys, tcell_data, user_id, user_valid=nil)
33
+ def initialize(request_env_or_header_keys,
34
+ tcell_data,
35
+ user_id,
36
+ password,
37
+ user_valid = nil)
26
38
  header_keys = Util.clean_header_keys(request_env_or_header_keys)
27
39
 
28
- super(header_keys, tcell_data, user_id, user_valid)
40
+ super(header_keys, tcell_data, user_id, password, user_valid)
29
41
 
30
- self["event_name"] = "login-failure"
42
+ self['event_name'] = 'login-failure'
31
43
  end
32
44
  end
33
45
 
34
46
  class LoginSuccess < LoginEvent
35
- def initialize(request_env_or_header_keys, tcell_data, user_id, user_valid=nil)
47
+ def initialize(request_env_or_header_keys,
48
+ tcell_data,
49
+ user_id,
50
+ password,
51
+ user_valid = nil)
36
52
  header_keys = Util.clean_header_keys(request_env_or_header_keys)
37
53
 
38
- super(header_keys, tcell_data, user_id, user_valid)
54
+ super(header_keys, tcell_data, user_id, password, user_valid)
39
55
 
40
- self["event_name"] = "login-success"
56
+ self['event_name'] = 'login-success'
41
57
  end
42
58
  end
43
59
  end
@@ -0,0 +1,21 @@
1
+ require 'tcell_agent/sensor_events/sensor'
2
+
3
+ module TCellAgent
4
+ module SensorEvents
5
+
6
+ class PatchesEvent < TCellSensorEvent
7
+ def initialize(rust_response, appsensor_meta)
8
+ super("patches")
9
+
10
+ self["patches_pid"] = rust_response["patches_policy_id"]
11
+ self["rule_id"] = rust_response["rule_id"]
12
+ self["action"] = "blocked"
13
+ self["sz"] = appsensor_meta.request_content_bytes_len if appsensor_meta.request_content_bytes_len
14
+ self["m"] = appsensor_meta.method if appsensor_meta.method
15
+ self["remote_addr"] = appsensor_meta.remote_address if appsensor_meta.remote_address
16
+ self["uri"] = TCellAgent::SensorEvents::Util.strip_uri_values(appsensor_meta.location) if appsensor_meta.location
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -31,13 +31,13 @@ module TCellAgent
31
31
  begin
32
32
  info = Etc.getpwnam(login)
33
33
  self["group"] = info.gid.to_s
34
- rescue Exception => te
34
+ rescue StandardError => te
35
35
  TCellAgent.logger.warn("Exception finding group id: #{te.message}")
36
36
  TCellAgent.logger.debug(te.backtrace)
37
37
  end
38
38
  end
39
39
 
40
- rescue Exception => to
40
+ rescue StandardError => to
41
41
  TCellAgent.logger.warn("Exception finding user & group: #{to.message}")
42
42
  TCellAgent.logger.debug(te.backtrace)
43
43
  end
@@ -78,7 +78,7 @@ module TCellAgent
78
78
  packages.push(package)
79
79
  TCellAgent.logger.debug("Adding packages #{x.name}")
80
80
  end
81
- rescue Exception => te
81
+ rescue StandardError => te
82
82
  TCellAgent.logger.error("Exception adding package: #{te.message}")
83
83
  TCellAgent.logger.debug(te.backtrace)
84
84
  end
@@ -11,10 +11,11 @@ module TCellAgent
11
11
  def self.jhash(str)
12
12
  str.each_char.reduce(0) do |result, char|
13
13
  [((result << 5) - result) + char.ord].pack('L').unpack('l').first
14
- end
14
+ end
15
15
  end
16
+
16
17
  def self.calculateRouteId(method, path, params=nil)
17
- route_id = jhash("#{method}|#{path}")
18
+ route_id = jhash("#{(method || "").downcase}|#{path}")
18
19
  if (route_id)
19
20
  route_id = route_id.to_s
20
21
  end
@@ -22,4 +23,4 @@ module TCellAgent
22
23
  end
23
24
  end
24
25
  end
25
- end
26
+ end
@@ -34,7 +34,7 @@ if defined?(Puma.cli_config)
34
34
  else
35
35
 
36
36
  # Runs initial instrumentation only once on the master process
37
- puma_server_starting = Proc.new { TCellAgent.run_instrumentation("Puma Cluster Mode") }
37
+ puma_server_starting = proc { TCellAgent.run_instrumentation("Puma Cluster Mode") }
38
38
 
39
39
  # before_fork was added in Puma v2.13.0
40
40
  if Puma.cli_config.options[:before_fork]
@@ -52,7 +52,7 @@ if defined?(Puma.cli_config)
52
52
  begin
53
53
  TCellAgent.logger.debug("Instrumenting: Puma Cluster Mode (Worker)")
54
54
  TCellAgent.thread_agent.start
55
- rescue Exception => e
55
+ rescue StandardError => e
56
56
  TCellAgent.logger.error("Could not start thread agent. #{e.message}")
57
57
  end
58
58
 
@@ -104,7 +104,7 @@ Unicorn::HttpServer.class_eval do
104
104
  TCellAgent.thread_agent.policy_polling_thread = nil
105
105
  TCellAgent.thread_agent.start
106
106
 
107
- rescue Exception => e
107
+ rescue StandardError => e
108
108
  TCellAgent.logger.error("Could not start thread agent. #{e.message}")
109
109
  end
110
110
  end
@@ -0,0 +1,28 @@
1
+ module TCellAgent
2
+ module Utils
3
+ module Passwords
4
+ def self.fingerprint_password(password, user_id)
5
+ digest = nil
6
+
7
+ app_id = TCellAgent.configuration.app_id
8
+ password_hmac_key = TCellAgent.configuration.password_hmac_key
9
+ if app_id &&
10
+ TCellAgent::Utils::Strings.present?(password_hmac_key) &&
11
+ TCellAgent::Utils::Strings.present?(password)
12
+ string_builder = [app_id, ':', password, ':']
13
+ string_builder.push(user_id) if user_id
14
+
15
+ digest = OpenSSL::HMAC.hexdigest(
16
+ OpenSSL::Digest.new('sha256'),
17
+ password_hmac_key.to_s,
18
+ string_builder.join('')
19
+ )
20
+
21
+ digest = digest[0...8]
22
+ end
23
+
24
+ digest
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,5 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
3
  module TCellAgent
4
- VERSION = "0.4.0"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/tcell_agent.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
+ require "tcell_agent/utils/passwords"
3
4
  require "tcell_agent/utils/strings"
4
5
  require "tcell_agent/utils/io"
5
6
  require 'tcell_agent/logger'
@@ -7,16 +8,11 @@ require 'tcell_agent/configuration'
7
8
 
8
9
  require 'tcell_agent/agent'
9
10
 
10
- require 'tcell_agent/appsensor/rules/appsensor_rule_manager'
11
-
12
11
  require 'tcell_agent/policies/content_security_policy'
13
12
  require 'tcell_agent/policies/http_tx_policy'
14
13
  require 'tcell_agent/policies/http_redirect_policy'
15
14
  require 'tcell_agent/policies/secure_headers_policy'
16
- require 'tcell_agent/policies/honeytokens_policy'
17
15
  require 'tcell_agent/policies/clickjacking_policy'
18
- require 'tcell_agent/policies/appsensor_policy'
19
- require 'tcell_agent/policies/patches_policy'
20
16
  require 'tcell_agent/policies/login_fraud_policy'
21
17
  require 'tcell_agent/policies/dataloss_policy'
22
18
 
@@ -0,0 +1,15 @@
1
+ {
2
+ "version":1,
3
+ "applications":
4
+ [
5
+ {
6
+ "name":"<name>",
7
+ "api_key":"<apikey>",
8
+ "fetch_policies_from_tcell":false,
9
+ "tcell_input_url":"https://localhost/",
10
+ "preload_policy_filename":"config/tcell_preload.json",
11
+ "logging_options":{"enabled":true, "level":"DEBUG"}
12
+ }
13
+ ]
14
+ }
15
+
File without changes