tcell_agent 1.1.12 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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