tcell_agent 1.1.12 → 2.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 (163) hide show
  1. checksums.yaml +5 -5
  2. data/bin/tcell_agent +26 -14
  3. data/lib/tcell_agent.rb +16 -10
  4. data/lib/tcell_agent/agent.rb +78 -97
  5. data/lib/tcell_agent/agent/route_manager.rb +0 -16
  6. data/lib/tcell_agent/agent/static_agent.rb +9 -30
  7. data/lib/tcell_agent/authlogic.rb +3 -6
  8. data/lib/tcell_agent/config/unknown_options.rb +4 -8
  9. data/lib/tcell_agent/configuration.rb +38 -119
  10. data/lib/tcell_agent/devise.rb +25 -27
  11. data/lib/tcell_agent/hooks/login_fraud.rb +30 -33
  12. data/lib/tcell_agent/instrument_servers.rb +25 -0
  13. data/lib/tcell_agent/instrumentation.rb +12 -10
  14. data/lib/tcell_agent/instrumentation/cmdi.rb +19 -15
  15. data/lib/tcell_agent/instrumentation/lfi.rb +73 -0
  16. data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +25 -0
  17. data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +123 -0
  18. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +159 -0
  19. data/lib/tcell_agent/logger.rb +50 -114
  20. data/lib/tcell_agent/patches.rb +6 -7
  21. data/lib/tcell_agent/policies/appfirewall_policy.rb +26 -0
  22. data/lib/tcell_agent/policies/command_injection_policy.rb +28 -0
  23. data/lib/tcell_agent/policies/dataloss_policy.rb +44 -44
  24. data/lib/tcell_agent/policies/headers_policy.rb +25 -0
  25. data/lib/tcell_agent/policies/http_redirect_policy.rb +13 -79
  26. data/lib/tcell_agent/policies/js_agent_policy.rb +27 -0
  27. data/lib/tcell_agent/policies/local_file_access.rb +28 -0
  28. data/lib/tcell_agent/policies/login_policy.rb +43 -0
  29. data/lib/tcell_agent/policies/patches_policy.rb +27 -0
  30. data/lib/tcell_agent/policies/policies_manager.rb +68 -0
  31. data/lib/tcell_agent/policies/policy_polling.rb +58 -0
  32. data/lib/tcell_agent/policies/policy_types.rb +14 -0
  33. data/lib/tcell_agent/policies/system_enablements.rb +27 -0
  34. data/lib/tcell_agent/rails/auth/authlogic.rb +43 -68
  35. data/lib/tcell_agent/rails/auth/devise.rb +20 -23
  36. data/lib/tcell_agent/rails/auth/doorkeeper.rb +63 -74
  37. data/lib/tcell_agent/rails/csrf_exception.rb +2 -2
  38. data/lib/tcell_agent/rails/dlp.rb +25 -15
  39. data/lib/tcell_agent/rails/dlp_handler.rb +1 -2
  40. data/lib/tcell_agent/rails/js_agent_insert.rb +12 -13
  41. data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +4 -25
  42. data/lib/tcell_agent/rails/middleware/context_middleware.rb +2 -12
  43. data/lib/tcell_agent/rails/middleware/global_middleware.rb +0 -1
  44. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +14 -34
  45. data/lib/tcell_agent/rails/on_start.rb +32 -31
  46. data/lib/tcell_agent/rails/routes.rb +7 -6
  47. data/lib/tcell_agent/rails/routes/grape.rb +1 -3
  48. data/lib/tcell_agent/rails/routes/route_id.rb +3 -1
  49. data/lib/tcell_agent/rails/settings_reporter.rb +23 -36
  50. data/lib/tcell_agent/rails/start_agent_after_initializers.rb +12 -0
  51. data/lib/tcell_agent/rails/tcell_body_proxy.rb +6 -4
  52. data/lib/tcell_agent/rust/agent_config.rb +49 -0
  53. data/lib/tcell_agent/rust/{libtcellagent-alpine-1.3.2.so → libtcellagent-4.14.0.dylib} +0 -0
  54. data/lib/tcell_agent/rust/libtcellagent-4.14.0.so +0 -0
  55. data/lib/tcell_agent/rust/{libtcellagent-1.3.2.so → libtcellagent-alpine-4.14.0.so} +0 -0
  56. data/lib/tcell_agent/rust/models.rb +0 -55
  57. data/lib/tcell_agent/rust/native_agent.rb +531 -0
  58. data/lib/tcell_agent/rust/native_agent_response.rb +42 -0
  59. data/lib/tcell_agent/rust/native_library.rb +68 -0
  60. data/lib/tcell_agent/rust/tcellagent-4.14.0.dll +0 -0
  61. data/lib/tcell_agent/sensor_events/agent_setting_event.rb +12 -0
  62. data/lib/tcell_agent/sensor_events/{app_config.rb → app_config_setting_event.rb} +0 -6
  63. data/lib/tcell_agent/sensor_events/dlp.rb +2 -6
  64. data/lib/tcell_agent/sensor_events/sensor.rb +0 -62
  65. data/lib/tcell_agent/sensor_events/server_agent.rb +13 -18
  66. data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +0 -108
  67. data/lib/tcell_agent/sensor_events/util/utils.rb +0 -2
  68. data/lib/tcell_agent/servers/passenger.rb +1 -28
  69. data/lib/tcell_agent/servers/puma.rb +3 -21
  70. data/lib/tcell_agent/servers/rails_server.rb +1 -1
  71. data/lib/tcell_agent/servers/thin.rb +2 -2
  72. data/lib/tcell_agent/servers/unicorn.rb +19 -80
  73. data/lib/tcell_agent/servers/webrick.rb +1 -1
  74. data/lib/tcell_agent/settings_reporter.rb +24 -24
  75. data/lib/tcell_agent/sinatra.rb +14 -16
  76. data/lib/tcell_agent/tcell_context.rb +40 -14
  77. data/lib/tcell_agent/utils/headers.rb +14 -0
  78. data/lib/tcell_agent/version.rb +1 -1
  79. data/spec/lib/tcell_agent/cmdi_spec.rb +0 -585
  80. data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -18
  81. data/spec/lib/tcell_agent/configuration_spec.rb +4 -140
  82. data/spec/lib/tcell_agent/hooks/login_fraud_spec.rb +46 -173
  83. data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +504 -0
  84. data/spec/lib/tcell_agent/instrumentation/cmdi/kernel_cmdi_spec.rb +435 -0
  85. data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +326 -0
  86. data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +556 -0
  87. data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +249 -0
  88. data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +105 -0
  89. data/spec/lib/tcell_agent/patches_spec.rb +25 -43
  90. data/spec/lib/tcell_agent/policies/appfirewall_policy_spec.rb +183 -0
  91. data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +57 -0
  92. data/spec/lib/tcell_agent/policies/command_injection_policy_spec.rb +84 -773
  93. data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +161 -0
  94. data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +9 -9
  95. data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +243 -198
  96. data/spec/lib/tcell_agent/policies/js_agent_policy_spec.rb +75 -0
  97. data/spec/lib/tcell_agent/policies/login_policy_spec.rb +165 -33
  98. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +84 -277
  99. data/spec/lib/tcell_agent/policies/policies_manager_spec.rb +104 -0
  100. data/spec/lib/tcell_agent/policies/policy_polling_spec.rb +6 -0
  101. data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +56 -0
  102. data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +9 -18
  103. data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +13 -30
  104. data/spec/lib/tcell_agent/rails/logger_spec.rb +27 -7
  105. data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +17 -12
  106. data/spec/lib/tcell_agent/rails/routes/routes_spec.rb +14 -14
  107. data/spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb +0 -35
  108. data/spec/lib/tcell_agent/settings_reporter_spec.rb +127 -153
  109. data/spec/spec_helper.rb +1 -1
  110. data/spec/support/builders.rb +104 -0
  111. data/spec/support/force_logger_mocking.rb +38 -0
  112. data/spec/support/resources/lfi_sample_file.txt +2 -0
  113. data/spec/support/static_agent_overrides.rb +0 -15
  114. metadata +63 -74
  115. data/lib/tcell_agent/agent/event_processor.rb +0 -326
  116. data/lib/tcell_agent/agent/fork_pipe_manager.rb +0 -113
  117. data/lib/tcell_agent/agent/policy_manager.rb +0 -219
  118. data/lib/tcell_agent/agent/policy_types.rb +0 -30
  119. data/lib/tcell_agent/api.rb +0 -91
  120. data/lib/tcell_agent/appsensor/injections_reporter.rb +0 -24
  121. data/lib/tcell_agent/config/child_process_events.rb +0 -8
  122. data/lib/tcell_agent/instrumentation/cmdi/backtick.rb +0 -10
  123. data/lib/tcell_agent/instrumentation/cmdi/exec.rb +0 -14
  124. data/lib/tcell_agent/instrumentation/cmdi/popen.rb +0 -28
  125. data/lib/tcell_agent/instrumentation/cmdi/spawn.rb +0 -11
  126. data/lib/tcell_agent/instrumentation/cmdi/system.rb +0 -11
  127. data/lib/tcell_agent/policies/http_tx_policy.rb +0 -60
  128. data/lib/tcell_agent/policies/login_fraud_policy.rb +0 -45
  129. data/lib/tcell_agent/policies/rust_policies.rb +0 -110
  130. data/lib/tcell_agent/rails.rb +0 -40
  131. data/lib/tcell_agent/rust/libtcellagent-1.3.2.dylib +0 -0
  132. data/lib/tcell_agent/rust/tcellagent-1.3.2.dll +0 -0
  133. data/lib/tcell_agent/rust/whisperer.rb +0 -308
  134. data/lib/tcell_agent/sensor_events/appsensor_event.rb +0 -52
  135. data/lib/tcell_agent/sensor_events/appsensor_meta_event.rb +0 -45
  136. data/lib/tcell_agent/sensor_events/command_injection.rb +0 -75
  137. data/lib/tcell_agent/sensor_events/honeytokens.rb +0 -16
  138. data/lib/tcell_agent/sensor_events/login_fraud.rb +0 -60
  139. data/lib/tcell_agent/sensor_events/metrics.rb +0 -123
  140. data/lib/tcell_agent/sensor_events/patches.rb +0 -21
  141. data/lib/tcell_agent/start_background_thread.rb +0 -55
  142. data/lib/tcell_agent/system_info.rb +0 -11
  143. data/lib/tcell_agent/utils/io.rb +0 -38
  144. data/lib/tcell_agent/utils/passwords.rb +0 -28
  145. data/lib/tcell_agent/utils/queue_with_timeout.rb +0 -142
  146. data/spec/lib/tcell_agent/agent/fork_pipe_manager_spec.rb +0 -100
  147. data/spec/lib/tcell_agent/agent/policy_manager_spec.rb +0 -535
  148. data/spec/lib/tcell_agent/agent/static_agent_spec.rb +0 -133
  149. data/spec/lib/tcell_agent/api/api_spec.rb +0 -39
  150. data/spec/lib/tcell_agent/appsensor/injections_reporter_spec.rb +0 -187
  151. data/spec/lib/tcell_agent/instrumentation_spec.rb +0 -225
  152. data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +0 -517
  153. data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +0 -22
  154. data/spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb +0 -293
  155. data/spec/lib/tcell_agent/rails/middleware/dlp_middleware_spec.rb +0 -198
  156. data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +0 -180
  157. data/spec/lib/tcell_agent/rails/middleware/redirect_middleware_spec.rb +0 -116
  158. data/spec/lib/tcell_agent/rust/models_spec.rb +0 -120
  159. data/spec/lib/tcell_agent/rust/whisperer_spec.rb +0 -704
  160. data/spec/lib/tcell_agent/sensor_events/appsensor_meta_event_spec.rb +0 -45
  161. data/spec/lib/tcell_agent/sensor_events/sessions_metric_spec.rb +0 -272
  162. data/spec/lib/tcell_agent/utils/bounded_queue_spec.rb +0 -52
  163. data/spec/lib/tcell_agent/utils/passwords_spec.rb +0 -143
@@ -0,0 +1,435 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kernel do
4
+ before(:each) do
5
+ native_agent = double('native_agent')
6
+ @command_injection_policy = TCellAgent::Policies::CommandInjectionPolicy.new(
7
+ native_agent, {}
8
+ )
9
+ end
10
+
11
+ describe '.backtick' do
12
+ context 'empty command' do
13
+ it 'should raise Errno::ENOENT' do
14
+ expect do
15
+ ``
16
+ end.to raise_error(Errno::ENOENT)
17
+ end
18
+ end
19
+
20
+ context 'with a non blocked command present' do
21
+ before(:each) do
22
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
23
+ end
24
+
25
+ context 'with command injection disabled' do
26
+ it 'should execute the command' do
27
+ expect(TCellAgent).to receive(:policy).with(
28
+ TCellAgent::PolicyTypes::COMMANDINJECTION
29
+ ).and_return(@command_injection_policy)
30
+ expect(@command_injection_policy).to receive(:enabled).and_return(false)
31
+ expect(@command_injection_policy).to_not receive(:block_command?)
32
+
33
+ `echo test`
34
+ end
35
+ end
36
+
37
+ context 'with command injection enabled' do
38
+ it 'should execute the command' do
39
+ expect(TCellAgent).to receive(:policy).with(
40
+ TCellAgent::PolicyTypes::COMMANDINJECTION
41
+ ).and_return(@command_injection_policy)
42
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
43
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(false)
44
+
45
+ `echo test`
46
+ end
47
+ end
48
+ end
49
+
50
+ context 'with a blocked command present' do
51
+ context 'with command injection enabled' do
52
+ it 'should raise a RuntimeError' do
53
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
54
+ expect(TCellAgent).to receive(:policy).with(
55
+ TCellAgent::PolicyTypes::COMMANDINJECTION
56
+ ).and_return(@command_injection_policy)
57
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
58
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true)
59
+
60
+ expect do
61
+ `echo test`
62
+ end.to raise_error(RuntimeError)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ describe '%x methods' do
69
+ context 'empty command' do
70
+ it 'should raise RuntimeError' do
71
+ expect do
72
+ ``
73
+ end.to raise_error(Errno::ENOENT)
74
+ end
75
+ end
76
+
77
+ context 'with a non blocked command present' do
78
+ before(:each) do
79
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
80
+ end
81
+
82
+ context 'with command injection disabled' do
83
+ it 'should execute the command' do
84
+ expect(TCellAgent).to receive(:policy).with(
85
+ TCellAgent::PolicyTypes::COMMANDINJECTION
86
+ ).and_return(@command_injection_policy)
87
+ expect(@command_injection_policy).to receive(:enabled).and_return(false)
88
+ expect(@command_injection_policy).to_not receive(:block_command?)
89
+
90
+ `echo test`
91
+ end
92
+ end
93
+
94
+ context 'with command injection enabled' do
95
+ it 'should execute the command' do
96
+ expect(TCellAgent).to receive(:policy).with(
97
+ TCellAgent::PolicyTypes::COMMANDINJECTION
98
+ ).and_return(@command_injection_policy)
99
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
100
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(false)
101
+
102
+ `echo test`
103
+ end
104
+ end
105
+ end
106
+
107
+ context 'with a blocked command present' do
108
+ context 'with command injection enabled' do
109
+ it 'should raise a RuntimeError' do
110
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
111
+ expect(TCellAgent).to receive(:policy).with(
112
+ TCellAgent::PolicyTypes::COMMANDINJECTION
113
+ ).and_return(@command_injection_policy)
114
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
115
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true)
116
+
117
+ expect do
118
+ `echo test`
119
+ end.to raise_error(RuntimeError)
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ describe '::open and #open' do
126
+ context 'empty command' do
127
+ it 'should raise an error' do
128
+ expect do
129
+ Kernel.open
130
+ end.to raise_error(ArgumentError)
131
+ expect do
132
+ Kernel.open(nil)
133
+ end.to raise_error(TypeError)
134
+ expect do
135
+ Kernel.open('')
136
+ end.to raise_error(Errno::ENOENT)
137
+ end
138
+ end
139
+
140
+ context 'name starts with a | operator' do
141
+ context 'with an empty or invalid command' do
142
+ it 'should raise an error' do
143
+ expect do
144
+ Kernel.open('|')
145
+ end.to raise_error(Errno::ENOENT)
146
+
147
+ expect do
148
+ Kernel.open('|invalid command')
149
+ end.to raise_error(Errno::ENOENT)
150
+
151
+ expect do
152
+ Kernel.open('|invalid command', 10)
153
+ end.to raise_error(Errno::ENOENT)
154
+ end
155
+ end
156
+ context 'with a valid command' do
157
+ it 'should execute the command' do
158
+ expect(Kernel.open('|echo test').read).to eq("test\n")
159
+ end
160
+ end
161
+ context 'with a non blocked command present' do
162
+ before(:each) do
163
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
164
+ end
165
+ context 'with command injection disabled' do
166
+ it 'should execute the command' do
167
+ expect(@command_injection_policy.enabled).to eq(false)
168
+
169
+ expect(TCellAgent).to receive(:policy).with(
170
+ TCellAgent::PolicyTypes::COMMANDINJECTION
171
+ ).and_return(@command_injection_policy)
172
+ expect(@command_injection_policy).to receive(:enabled).and_call_original
173
+ expect(@command_injection_policy).to_not receive(:block_command?)
174
+
175
+ expect(Kernel.open('|echo test').read).to eq("test\n")
176
+ end
177
+ end
178
+
179
+ context 'with command injection enabled' do
180
+ it 'should execute the command' do
181
+ expect(TCellAgent).to receive(:policy).with(
182
+ TCellAgent::PolicyTypes::COMMANDINJECTION
183
+ ).and_return(@command_injection_policy)
184
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
185
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(false)
186
+
187
+ expect(Kernel.open('|echo test').read).to eq("test\n")
188
+ end
189
+ end
190
+ end
191
+
192
+ context 'with a blocked command present' do
193
+ context 'with command injection enabled' do
194
+ it 'should raise a RuntimeError' do
195
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
196
+
197
+ expect(TCellAgent).to receive(:policy).with(
198
+ TCellAgent::PolicyTypes::COMMANDINJECTION
199
+ ).and_return(@command_injection_policy)
200
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
201
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true)
202
+
203
+ expect do
204
+ Kernel.open('|echo test')
205
+ end.to raise_error(RuntimeError)
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end
211
+ describe '.spawn and Kernel.spawn' do
212
+ context 'empty command' do
213
+ it 'should raise an error' do
214
+ expect do
215
+ spawn
216
+ end.to raise_error(ArgumentError)
217
+ expect do
218
+ Kernel.spawn
219
+ end.to raise_error(ArgumentError)
220
+ expect do
221
+ spawn(nil)
222
+ end.to raise_error(TypeError)
223
+ expect do
224
+ Kernel.spawn(nil)
225
+ end.to raise_error(TypeError)
226
+ expect do
227
+ spawn('')
228
+ end.to raise_error(Errno::ENOENT)
229
+ expect do
230
+ Kernel.spawn('')
231
+ end.to raise_error(Errno::ENOENT)
232
+ end
233
+ end
234
+
235
+ context 'non existent command' do
236
+ it 'should raise error' do
237
+ expect do
238
+ spawn('foobar')
239
+ end.to raise_error(Errno::ENOENT)
240
+ expect do
241
+ Kernel.spawn('foobar')
242
+ end.to raise_error(Errno::ENOENT)
243
+ end
244
+ end
245
+
246
+ context 'with a valid command' do
247
+ it 'should execute command' do
248
+ pid = spawn('echo test > /dev/null 2>&1')
249
+ expect(pid).to_not be_nil
250
+
251
+ pid = spawn(RbConfig.ruby, "-e'Hello World!'", '>', '/dev/null', '2>&1')
252
+ expect(pid).to_not be_nil
253
+
254
+ pid = Kernel.spawn('echo test > /dev/null 2>&1')
255
+ expect(pid).to_not be_nil
256
+
257
+ pid = Kernel.spawn(RbConfig.ruby, "-e'Hello World!'", '>', '/dev/null', '2>&1')
258
+ expect(pid).to_not be_nil
259
+ end
260
+ end
261
+
262
+ context 'with a non blocked command present' do
263
+ before(:each) do
264
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
265
+ end
266
+
267
+ context 'with command injection disabled' do
268
+ it 'should execute the command' do
269
+ expect(TCellAgent).to receive(:policy).with(
270
+ TCellAgent::PolicyTypes::COMMANDINJECTION
271
+ ).and_return(@command_injection_policy, @command_injection_policy)
272
+ expect(@command_injection_policy).to receive(:enabled).and_return(false, false)
273
+ expect(@command_injection_policy).to_not receive(:block_command?)
274
+
275
+ spawn('echo test > /dev/null 2>&1')
276
+ Kernel.spawn('echo test > /dev/null 2>&1')
277
+ end
278
+ end
279
+
280
+ context 'with command injection enabled' do
281
+ it 'should execute the command' do
282
+ expect(TCellAgent).to receive(:policy).with(
283
+ TCellAgent::PolicyTypes::COMMANDINJECTION
284
+ ).and_return(@command_injection_policy, @command_injection_policy)
285
+ expect(@command_injection_policy).to receive(:enabled).and_return(true, true)
286
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test > /dev/null 2>&1', nil).and_return(false, false)
287
+
288
+ spawn('echo test > /dev/null 2>&1')
289
+ Kernel.spawn('echo test > /dev/null 2>&1')
290
+ end
291
+ end
292
+ end
293
+
294
+ context 'with a blocked command present' do
295
+ context 'with command injection enabled' do
296
+ it 'should raise a RuntimeError' do
297
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
298
+ expect(TCellAgent).to receive(:policy).with(
299
+ TCellAgent::PolicyTypes::COMMANDINJECTION
300
+ ).and_return(@command_injection_policy, @command_injection_policy)
301
+ expect(@command_injection_policy).to receive(:enabled).and_return(true, true)
302
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true, true)
303
+
304
+ expect do
305
+ spawn('echo test')
306
+ end.to raise_error(RuntimeError)
307
+ expect do
308
+ Kernel.spawn('echo test')
309
+ end.to raise_error(RuntimeError)
310
+ end
311
+ end
312
+ end
313
+ end
314
+
315
+ describe '.system and Kernel.system' do
316
+ context 'empty command' do
317
+ it 'should raise an error' do
318
+ expect do
319
+ system
320
+ end.to raise_error(ArgumentError)
321
+ expect do
322
+ Kernel.system
323
+ end.to raise_error(ArgumentError)
324
+ expect do
325
+ system(nil)
326
+ end.to raise_error(TypeError)
327
+ expect do
328
+ Kernel.system(nil)
329
+ end.to raise_error(TypeError)
330
+ expect(system('')).to be_nil
331
+ expect(Kernel.system('')).to be_nil
332
+ end
333
+ end
334
+
335
+ context 'non existent command' do
336
+ it 'should return nil' do
337
+ expect(system('foobar')).to be_nil
338
+ expect(Kernel.system('foobar')).to be_nil
339
+ end
340
+ end
341
+
342
+ context 'with a valid command' do
343
+ it 'should execute command' do
344
+ pid = system('echo test > /dev/null 2>&1')
345
+ expect(pid).to eq(true)
346
+
347
+ pid = system(RbConfig.ruby, "-e'Hello World!'", '>', '/dev/null', '2>&1')
348
+ expect(pid).to eq(true)
349
+
350
+ pid = Kernel.system('echo test > /dev/null 2>&1')
351
+ expect(pid).to eq(true)
352
+
353
+ pid = Kernel.system(RbConfig.ruby, "-e'Hello World!'", '>', '/dev/null', '2>&1')
354
+ expect(pid).to eq(true)
355
+ end
356
+ end
357
+
358
+ context 'with a non blocked command present' do
359
+ before(:each) do
360
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
361
+ end
362
+
363
+ context 'with command injection disabled' do
364
+ it 'should execute the command' do
365
+ expect(TCellAgent).to receive(:policy).with(
366
+ TCellAgent::PolicyTypes::COMMANDINJECTION
367
+ ).and_return(@command_injection_policy, @command_injection_policy)
368
+ expect(@command_injection_policy).to receive(:enabled).and_return(false, false)
369
+ expect(@command_injection_policy).to_not receive(:block_command?)
370
+
371
+ system('echo test > /dev/null 2>&1')
372
+ Kernel.system('echo test > /dev/null 2>&1')
373
+ end
374
+ end
375
+
376
+ context 'with command injection enabled' do
377
+ it 'should execute the command' do
378
+ expect(TCellAgent).to receive(:policy).with(
379
+ TCellAgent::PolicyTypes::COMMANDINJECTION
380
+ ).and_return(@command_injection_policy, @command_injection_policy)
381
+ expect(@command_injection_policy).to receive(:enabled).and_return(true, true)
382
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test > /dev/null 2>&1', nil).and_return(false, false)
383
+
384
+ system('echo test > /dev/null 2>&1')
385
+ Kernel.system('echo test > /dev/null 2>&1')
386
+ end
387
+ end
388
+ end
389
+
390
+ context 'with a blocked command present' do
391
+ context 'with command injection enabled' do
392
+ it 'should raise a RuntimeError' do
393
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
394
+
395
+ expect(TCellAgent).to receive(:policy).with(
396
+ TCellAgent::PolicyTypes::COMMANDINJECTION
397
+ ).and_return(@command_injection_policy, @command_injection_policy)
398
+ expect(@command_injection_policy).to receive(:enabled).and_return(true, true)
399
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true, true)
400
+
401
+ expect do
402
+ system('echo test')
403
+ end.to raise_error(RuntimeError)
404
+ expect do
405
+ Kernel.system('echo test')
406
+ end.to raise_error(RuntimeError)
407
+ end
408
+ end
409
+ end
410
+ end
411
+
412
+ describe '.exec' do
413
+ # can only test this case since exec replaces current process with new process
414
+ context 'with a blocked command present' do
415
+ context 'with command injection enabled' do
416
+ it 'should raise a RuntimeError' do
417
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
418
+
419
+ expect(TCellAgent).to receive(:policy).with(
420
+ TCellAgent::PolicyTypes::COMMANDINJECTION
421
+ ).and_return(@command_injection_policy, @command_injection_policy)
422
+ expect(@command_injection_policy).to receive(:enabled).and_return(true, true)
423
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true, true)
424
+
425
+ expect do
426
+ exec('echo test')
427
+ end.to raise_error(RuntimeError)
428
+ expect do
429
+ Kernel.exec('echo test')
430
+ end.to raise_error(RuntimeError)
431
+ end
432
+ end
433
+ end
434
+ end
435
+ end
@@ -0,0 +1,326 @@
1
+ require 'spec_helper'
2
+ require 'securerandom'
3
+
4
+ describe 'File' do
5
+ before(:all) do
6
+ native_agent = double('native_agent')
7
+ @local_files_policy = TCellAgent::Policies::LocalFileInclusion.new(
8
+ native_agent, {}
9
+ )
10
+ @system_enablements_policy = TCellAgent::Policies::SystemEnablements.new(
11
+ native_agent, {}
12
+ )
13
+ @filename = get_test_resource_path('lfi_sample_file.txt')
14
+ @file_contents = "This is line one.\nThis is line two.\n"
15
+ @new_file_name = '/tmp/' + SecureRandom.uuid
16
+ end
17
+
18
+ describe '.new' do
19
+ context 'empty path' do
20
+ it 'should raise an error' do
21
+ expect do
22
+ File.new
23
+ end.to raise_error(ArgumentError)
24
+ expect do
25
+ File.new(nil)
26
+ end.to raise_error(TypeError)
27
+ expect do
28
+ File.new('')
29
+ end.to raise_error(Errno::ENOENT)
30
+ end
31
+ end
32
+ context 'with a non-existent file' do
33
+ context 'with a directory not blocked for read/write' do
34
+ before(:each) do
35
+ expect(TCellAgent).to receive(:policy).with(
36
+ TCellAgent::PolicyTypes::LFI
37
+ ).and_return(@local_files_policy)
38
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
39
+ end
40
+ context 'with a filename and mode r' do
41
+ it 'should raise an ERRNO::ENOENT error' do
42
+ expect do
43
+ File.new(@new_file_name, 'r')
44
+ end.to raise_error(Errno::ENOENT)
45
+ end
46
+ end
47
+ context 'with a filename and mode w' do
48
+ it 'should create the file' do
49
+ File.new(@new_file_name, 'w')
50
+
51
+ expect(File.exist?(@new_file_name)).to be_truthy
52
+ File.delete(@new_file_name)
53
+ end
54
+ end
55
+ context 'with a filename and write mode and file permissions 644' do
56
+ it 'should create the file with the correct permissions' do
57
+ File.new(@new_file_name, 'w', 0o644)
58
+
59
+ expect(File.exist?(@new_file_name)).to be_truthy
60
+ expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('644')
61
+ File.delete(@new_file_name)
62
+ end
63
+ end
64
+ context 'with a filename and write mode and file permissions 755' do
65
+ it 'should create the file with the correct permissions' do
66
+ File.new(@new_file_name, 'w', 0o755)
67
+
68
+ expect(File.exist?(@new_file_name)).to be_truthy
69
+ expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
70
+ File.delete(@new_file_name)
71
+ end
72
+ end
73
+ context 'with a filename and write mode and file permissions 777' do
74
+ it 'should create the file with permissions 755' do
75
+ File.new(@new_file_name, 'w', 0o777)
76
+
77
+ expect(File.exist?(@new_file_name)).to be_truthy
78
+ expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
79
+ File.delete(@new_file_name)
80
+ end
81
+ end
82
+ end
83
+ context 'with a filename blocked for read/write' do
84
+ before(:each) do
85
+ expect(TCellAgent).to receive(:policy).with(
86
+ TCellAgent::PolicyTypes::LFI
87
+ ).and_return(@local_files_policy)
88
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
89
+ end
90
+ context 'with a filename and write mode' do
91
+ it 'should raise an IOError' do
92
+ expect do
93
+ File.new(@new_file_name, 'w')
94
+ end.to raise_error(IOError)
95
+ end
96
+ end
97
+ context 'with a filename and write mode and file permissions 644' do
98
+ it 'should raise an IOError' do
99
+ expect do
100
+ File.new(@new_file_name, 'w', 644)
101
+ end.to raise_error(IOError)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ context 'with an existing file' do
107
+ context 'with a file not blocked for read/write' do
108
+ before(:each) do
109
+ expect(TCellAgent).to receive(:policy).with(
110
+ TCellAgent::PolicyTypes::LFI
111
+ ).and_return(@local_files_policy)
112
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
113
+ end
114
+ context 'with a filename' do
115
+ it 'should still be able to read the file' do
116
+ result = File.new(@filename).read
117
+ expect(result).to eq @file_contents
118
+ end
119
+ end
120
+ context 'with a filename and mode r' do
121
+ it 'should still be able to read the file' do
122
+ result = File.new(@filename, 'r').read
123
+ expect(result).to eq @file_contents
124
+ end
125
+ end
126
+ context 'with a filenname and mode w' do
127
+ it 'should still be able to write to a file' do
128
+ file = File.new('/dev/null', 'w')
129
+ expect(file.write('dummy message')).to eq 13
130
+ end
131
+ end
132
+ context 'with a filenname and mode a' do
133
+ it 'should still be able to write to a file' do
134
+ file = File.new('/dev/null', 'a')
135
+ expect(file.write('dummy message')).to eq 13
136
+ end
137
+ end
138
+ end
139
+ context 'with a file blocked for read/write' do
140
+ before(:each) do
141
+ expect(TCellAgent).to receive(:policy).with(
142
+ TCellAgent::PolicyTypes::LFI
143
+ ).and_return(@local_files_policy)
144
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
145
+ end
146
+ context 'with a filename' do
147
+ it 'should not be able to read the file' do
148
+ expect do
149
+ File.new(@filename)
150
+ end.to raise_error(IOError)
151
+ end
152
+ end
153
+ context 'with a filename and mode r' do
154
+ it 'should not be able to read the file' do
155
+ expect do
156
+ File.new(@filename, 'r')
157
+ end.to raise_error(IOError)
158
+ end
159
+ end
160
+ context 'with a filename and mode w' do
161
+ it 'should not be able to write to the file' do
162
+ expect do
163
+ File.new('/dev/null', 'w')
164
+ end.to raise_error(IOError)
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ describe '.open' do
172
+ context 'empty path' do
173
+ it 'should raise an error' do
174
+ expect do
175
+ File.open
176
+ end.to raise_error(ArgumentError)
177
+ expect do
178
+ File.open(nil)
179
+ end.to raise_error(TypeError)
180
+ expect do
181
+ File.open('')
182
+ end.to raise_error(Errno::ENOENT)
183
+ end
184
+ end
185
+ context 'with a non-existent file' do
186
+ before(:all) do
187
+ @new_file_name = '/tmp/' + SecureRandom.uuid
188
+ end
189
+ context 'with a directory not blocked for read/write' do
190
+ before(:each) do
191
+ expect(TCellAgent).to receive(:policy).with(
192
+ TCellAgent::PolicyTypes::LFI
193
+ ).and_return(@local_files_policy)
194
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
195
+ end
196
+ context 'with a filename and mode r' do
197
+ it 'should raise an ERRNO::ENOENT error' do
198
+ expect do
199
+ File.open(@new_file_name, 'r')
200
+ end.to raise_error(Errno::ENOENT)
201
+ end
202
+ end
203
+ context 'with a filename and mode w' do
204
+ it 'should create the file' do
205
+ File.open(@new_file_name, 'w')
206
+
207
+ expect(File.exist?(@new_file_name)).to be_truthy
208
+ File.delete(@new_file_name)
209
+ end
210
+ end
211
+ context 'with a filename and write mode and file permissions 644' do
212
+ it 'should create the file with the correct permissions' do
213
+ File.open(@new_file_name, 'w', 0o644)
214
+
215
+ expect(File.exist?(@new_file_name)).to be_truthy
216
+ expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('644')
217
+ File.delete(@new_file_name)
218
+ end
219
+ end
220
+ context 'with a filename and write mode and file permissions 755' do
221
+ it 'should create the file with the correct permissions' do
222
+ File.open(@new_file_name, 'w', 0o755)
223
+
224
+ expect(File.exist?(@new_file_name)).to be_truthy
225
+ expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
226
+ File.delete(@new_file_name)
227
+ end
228
+ end
229
+ context 'with a filename and write mode and file permissions 777' do
230
+ it 'should create the file with permissions 755' do
231
+ File.open(@new_file_name, 'w', 0o777)
232
+
233
+ expect(File.exist?(@new_file_name)).to be_truthy
234
+ expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
235
+ File.delete(@new_file_name)
236
+ end
237
+ end
238
+ end
239
+ context 'with a filename blocked for read/write' do
240
+ before(:each) do
241
+ expect(TCellAgent).to receive(:policy).with(
242
+ TCellAgent::PolicyTypes::LFI
243
+ ).and_return(@local_files_policy)
244
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
245
+ end
246
+ context 'with a filename and write mode' do
247
+ it 'should raise an IOError' do
248
+ expect do
249
+ File.open(@new_file_name, 'w')
250
+ end.to raise_error(IOError)
251
+ end
252
+ end
253
+ context 'with a filename and write mode and file permissions 644' do
254
+ it 'should raise an IOError' do
255
+ expect do
256
+ File.open(@new_file_name, 'w', 644)
257
+ end.to raise_error(IOError)
258
+ end
259
+ end
260
+ end
261
+ end
262
+ context 'with an existing file' do
263
+ context 'with a file not blocked for read/write' do
264
+ before(:each) do
265
+ expect(TCellAgent).to receive(:policy).with(
266
+ TCellAgent::PolicyTypes::LFI
267
+ ).and_return(@local_files_policy)
268
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
269
+ end
270
+ context 'with a filename' do
271
+ it 'should still be able to read the file' do
272
+ result = File.open(@filename).read
273
+ expect(result).to eq @file_contents
274
+ end
275
+ end
276
+ context 'with a filename and mode r' do
277
+ it 'should still be able to read the file' do
278
+ result = File.open(@filename, 'r').read
279
+ expect(result).to eq @file_contents
280
+ end
281
+ end
282
+ context 'with a filenname and mode w' do
283
+ it 'should still be able to write to a file' do
284
+ file = File.open('/dev/null', 'w')
285
+ expect(file.write('dummy message')).to eq 13
286
+ end
287
+ end
288
+ context 'with a filenname and mode a' do
289
+ it 'should still be able to write to a file' do
290
+ file = File.open('/dev/null', 'a')
291
+ expect(file.write('dummy message')).to eq 13
292
+ end
293
+ end
294
+ end
295
+ context 'with a file blocked for read/write' do
296
+ before(:each) do
297
+ expect(TCellAgent).to receive(:policy).with(
298
+ TCellAgent::PolicyTypes::LFI
299
+ ).and_return(@local_files_policy)
300
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
301
+ end
302
+ context 'with a filename' do
303
+ it 'should not be able to read the file' do
304
+ expect do
305
+ File.open(@filename)
306
+ end.to raise_error(IOError)
307
+ end
308
+ end
309
+ context 'with a filename and mode r' do
310
+ it 'should not be able to read the file' do
311
+ expect do
312
+ File.open(@filename, 'r')
313
+ end.to raise_error(IOError)
314
+ end
315
+ end
316
+ context 'with a filename and mode w' do
317
+ it 'should not be able to write to the file' do
318
+ expect do
319
+ File.open('/dev/null', 'w')
320
+ end.to raise_error(IOError)
321
+ end
322
+ end
323
+ end
324
+ end
325
+ end
326
+ end