tcell_agent 2.0.0 → 2.5.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.
- checksums.yaml +4 -4
- data/LICENSE +2 -2
- data/bin/tcell_agent +41 -150
- data/lib/tcell_agent/agent.rb +87 -52
- data/lib/tcell_agent/config_initializer.rb +63 -0
- data/lib/tcell_agent/configuration.rb +72 -267
- data/lib/tcell_agent/hooks/login_fraud.rb +1 -1
- data/lib/tcell_agent/instrument_servers.rb +14 -18
- data/lib/tcell_agent/instrumentation/cmdi.rb +47 -15
- data/lib/tcell_agent/instrumentation/lfi.rb +72 -15
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/file.rb +21 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/io.rb +75 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/kernel.rb +80 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/file.rb +21 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/io.rb +75 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/kernel.rb +80 -0
- data/lib/tcell_agent/instrumentation.rb +14 -6
- data/lib/tcell_agent/logger.rb +3 -4
- data/lib/tcell_agent/policies/command_injection_policy.rb +1 -1
- data/lib/tcell_agent/policies/dataloss_policy.rb +15 -8
- data/lib/tcell_agent/policies/headers_policy.rb +2 -2
- data/lib/tcell_agent/policies/patches_policy.rb +8 -4
- data/lib/tcell_agent/policies/policies_manager.rb +1 -0
- data/lib/tcell_agent/policies/policy_polling.rb +4 -3
- data/lib/tcell_agent/rails/auth/authlogic.rb +49 -44
- data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
- data/lib/tcell_agent/rails/auth/devise.rb +103 -102
- data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
- data/lib/tcell_agent/rails/auth/doorkeeper.rb +54 -57
- data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
- data/lib/tcell_agent/rails/better_ip.rb +7 -19
- data/lib/tcell_agent/rails/csrf_exception.rb +0 -8
- data/lib/tcell_agent/rails/dlp/process_request.rb +5 -0
- data/lib/tcell_agent/rails/dlp.rb +58 -56
- data/lib/tcell_agent/rails/dlp_handler.rb +9 -10
- data/lib/tcell_agent/rails/js_agent_insert.rb +2 -3
- data/lib/tcell_agent/rails/middleware/context_middleware.rb +2 -1
- data/lib/tcell_agent/rails/middleware/global_middleware.rb +3 -4
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +1 -0
- data/lib/tcell_agent/rails/{on_start.rb → railties/tcell_agent_railties.rb} +9 -16
- data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
- data/lib/tcell_agent/rails/routes/grape.rb +5 -12
- data/lib/tcell_agent/rails/routes.rb +6 -9
- data/lib/tcell_agent/rails/settings_reporter.rb +3 -6
- data/lib/tcell_agent/rails/tcell_body_proxy.rb +4 -7
- data/lib/tcell_agent/routes/table.rb +3 -0
- data/lib/tcell_agent/rust/agent_config.rb +62 -33
- data/lib/tcell_agent/rust/{libtcellagent-4.14.0.so → libtcellagent-alpine.so} +0 -0
- data/lib/tcell_agent/rust/{libtcellagent-4.14.0.dylib → libtcellagent-x64.dll} +0 -0
- data/lib/tcell_agent/rust/{libtcellagent-alpine-4.14.0.so → libtcellagent.dylib} +0 -0
- data/lib/tcell_agent/rust/libtcellagent.so +0 -0
- data/lib/tcell_agent/rust/models.rb +9 -0
- data/lib/tcell_agent/rust/native_agent.rb +61 -51
- data/lib/tcell_agent/rust/native_library.rb +8 -10
- data/lib/tcell_agent/sensor_events/server_agent.rb +3 -100
- data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +1 -0
- data/lib/tcell_agent/servers/puma.rb +30 -13
- data/lib/tcell_agent/servers/rack_puma_handler.rb +33 -0
- data/lib/tcell_agent/servers/rails_server.rb +4 -4
- data/lib/tcell_agent/servers/unicorn.rb +1 -1
- data/lib/tcell_agent/servers/webrick.rb +12 -3
- data/lib/tcell_agent/settings_reporter.rb +0 -93
- data/lib/tcell_agent/sinatra.rb +1 -0
- data/lib/tcell_agent/tcell_context.rb +16 -7
- data/lib/tcell_agent/utils/headers.rb +0 -1
- data/lib/tcell_agent/utils/strings.rb +2 -2
- data/lib/tcell_agent/version.rb +1 -1
- data/lib/tcell_agent.rb +8 -16
- data/spec/cruby_spec_helper.rb +26 -0
- data/spec/lib/tcell_agent/configuration_spec.rb +62 -212
- data/spec/lib/tcell_agent/instrument_servers_spec.rb +95 -0
- data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +2 -2
- data/spec/lib/tcell_agent/{cmdi_spec.rb → instrumentation/cmdi_spec.rb} +50 -0
- data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +211 -272
- data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +213 -223
- data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +95 -61
- data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +120 -2
- data/spec/lib/tcell_agent/patches_spec.rb +2 -1
- data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +1 -2
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +5 -6
- data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +21 -2
- data/spec/lib/tcell_agent/policies/policies_manager_spec.rb +1 -1
- data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +13 -8
- data/spec/lib/tcell_agent/rails/better_ip_spec.rb +9 -11
- data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +6 -6
- data/spec/lib/tcell_agent/rails/dlp_spec.rb +1 -0
- data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +10 -2
- data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +2 -1
- data/spec/lib/tcell_agent/rails/routes/route_id_spec.rb +4 -4
- data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
- data/spec/lib/tcell_agent/settings_reporter_spec.rb +2 -89
- data/spec/lib/tcell_agent/tcell_context_spec.rb +6 -5
- data/spec/spec_helper.rb +9 -1
- data/spec/support/builders.rb +8 -7
- data/spec/support/server_mocks/passenger_mock.rb +7 -0
- data/spec/support/server_mocks/puma_mock.rb +21 -0
- data/spec/support/server_mocks/rails_mock.rb +7 -0
- data/spec/support/server_mocks/thin_mock.rb +7 -0
- data/spec/support/server_mocks/unicorn_mock.rb +11 -0
- data/spec/support/shared_spec.rb +29 -0
- data/tcell_agent.gemspec +14 -14
- metadata +46 -29
- data/Rakefile +0 -18
- data/lib/tcell_agent/authlogic.rb +0 -23
- data/lib/tcell_agent/config/unknown_options.rb +0 -119
- data/lib/tcell_agent/devise.rb +0 -33
- data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +0 -25
- data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +0 -123
- data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +0 -159
- data/lib/tcell_agent/rails/start_agent_after_initializers.rb +0 -12
- data/lib/tcell_agent/rust/tcellagent-4.14.0.dll +0 -0
- data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -195
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# rubocop:disable Lint/UselessAssignment
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
require 'securerandom'
|
|
5
|
+
require 'pathname'
|
|
5
6
|
|
|
6
7
|
describe 'Kernel' do
|
|
7
8
|
before do
|
|
@@ -14,11 +15,12 @@ describe 'Kernel' do
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
before(:all) do
|
|
17
|
-
@new_file_name =
|
|
18
|
+
@new_file_name = NEW_FILE_NAME
|
|
19
|
+
@new_pathname = Pathname.new(@new_file_name)
|
|
18
20
|
end
|
|
19
21
|
describe '#open and ::open' do
|
|
20
22
|
context 'empty path' do
|
|
21
|
-
it '
|
|
23
|
+
it 'raises an error' do
|
|
22
24
|
expect do
|
|
23
25
|
Kernel.open
|
|
24
26
|
end.to raise_error(ArgumentError)
|
|
@@ -39,106 +41,138 @@ describe 'Kernel' do
|
|
|
39
41
|
end.to raise_error(Errno::ENOENT)
|
|
40
42
|
end
|
|
41
43
|
end
|
|
42
|
-
context 'with
|
|
44
|
+
context 'with filename not blocked for read/write' do
|
|
43
45
|
before do |test|
|
|
44
46
|
unless test.metadata[:skip_before]
|
|
45
47
|
expect(TCellAgent).to receive(:policy).with(
|
|
46
48
|
TCellAgent::PolicyTypes::LFI
|
|
47
49
|
).and_return(@local_files_policy, @local_files_policy)
|
|
48
50
|
expect(@local_files_policy).to receive(:block_file_access?).and_return(false, false)
|
|
51
|
+
expect(TCellAgent::Cmdi).not_to receive(:parse_command_from_open)
|
|
49
52
|
end
|
|
50
53
|
end
|
|
51
54
|
|
|
52
|
-
it '
|
|
55
|
+
it 'executes OS commands', :skip_before do
|
|
53
56
|
result = Kernel.open('|echo test').read
|
|
54
57
|
expect(result).to eq "test\n"
|
|
55
58
|
|
|
56
59
|
result = open('|echo test').read
|
|
57
60
|
expect(result).to eq "test\n"
|
|
58
61
|
end
|
|
59
|
-
context 'with a nonexistent filename with mode w' do
|
|
60
|
-
it 'should create the file' do
|
|
61
|
-
Kernel.open(@new_file_name, 'w')
|
|
62
|
-
expect(File.exist?(@new_file_name)).to be_truthy
|
|
63
|
-
File.delete(@new_file_name)
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
it 'creates the file when passed a pathname' do
|
|
64
|
+
Kernel.open(@new_pathname, 'w')
|
|
65
|
+
expect(File.exist?(@new_pathname)).to be_truthy
|
|
66
|
+
File.delete(@new_pathname)
|
|
67
|
+
|
|
68
|
+
open(@new_pathname, 'w')
|
|
69
|
+
expect(File.exist?(@new_pathname)).to be_truthy
|
|
70
|
+
File.delete(@new_pathname)
|
|
69
71
|
end
|
|
70
|
-
context 'with a filename and mode w and file permissions 644' do
|
|
71
|
-
it 'should create the file with the correct permissions' do
|
|
72
|
-
Kernel.open(@new_file_name, 'w', 0o644)
|
|
73
|
-
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('644')
|
|
74
|
-
File.delete(@new_file_name)
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
it 'creates the file when passed a string' do
|
|
74
|
+
Kernel.open(@new_file_name, 'w')
|
|
75
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
76
|
+
File.delete(@new_file_name)
|
|
77
|
+
|
|
78
|
+
open(@new_file_name, 'w')
|
|
79
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
80
|
+
File.delete(@new_file_name)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'creates the file with the permission 644' do
|
|
84
|
+
Kernel.open(@new_file_name, 'w', 0o644)
|
|
85
|
+
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('644')
|
|
86
|
+
File.delete(@new_file_name)
|
|
87
|
+
|
|
88
|
+
open(@new_file_name, 'w', 0o644)
|
|
89
|
+
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('644')
|
|
90
|
+
File.delete(@new_file_name)
|
|
80
91
|
end
|
|
81
|
-
context 'with a filename and mode w and file permissions 777' do
|
|
82
|
-
it 'should create the file with the correct permissions 755' do
|
|
83
|
-
Kernel.open(@new_file_name, 'w', 0o777)
|
|
84
|
-
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
|
|
85
|
-
File.delete(@new_file_name)
|
|
86
92
|
|
|
87
|
-
|
|
93
|
+
it 'creates the file with the permission 755' do
|
|
94
|
+
Kernel.open(@new_file_name, 'w', 0o777)
|
|
95
|
+
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
|
|
96
|
+
File.delete(@new_file_name)
|
|
97
|
+
|
|
98
|
+
open(@new_file_name, 'w', 0o777)
|
|
99
|
+
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
|
|
100
|
+
File.delete(@new_file_name)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context 'using mode, perm, binmode', :skip_before do
|
|
104
|
+
before(:each) do
|
|
105
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
106
|
+
TCellAgent::PolicyTypes::LFI
|
|
107
|
+
).and_return(@local_files_policy)
|
|
108
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
109
|
+
expect(TCellAgent::Cmdi).not_to receive(:parse_command_from_open)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
after :each do
|
|
88
113
|
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
|
|
89
|
-
|
|
114
|
+
expect(@result.binmode?).to eq true
|
|
115
|
+
|
|
116
|
+
File.delete(NEW_FILE_NAME) if File.exist?(NEW_FILE_NAME)
|
|
90
117
|
end
|
|
118
|
+
|
|
119
|
+
test_ruby2_ruby3_keywords(Kernel,
|
|
120
|
+
'open',
|
|
121
|
+
[NEW_FILE_NAME, 'w', 0o755],
|
|
122
|
+
{ :binmode => true },
|
|
123
|
+
nil)
|
|
124
|
+
|
|
125
|
+
test_ruby2_ruby3_keywords(Object,
|
|
126
|
+
'open',
|
|
127
|
+
[NEW_FILE_NAME, 'w', 0o755],
|
|
128
|
+
{ :binmode => true },
|
|
129
|
+
nil)
|
|
91
130
|
end
|
|
92
131
|
end
|
|
93
|
-
context 'with
|
|
132
|
+
context 'with filename blocked for read/write' do
|
|
94
133
|
before do |test|
|
|
95
134
|
unless test.metadata[:skip_before]
|
|
96
135
|
expect(TCellAgent).to receive(:policy).with(
|
|
97
136
|
TCellAgent::PolicyTypes::LFI
|
|
98
137
|
).and_return(@local_files_policy, @local_files_policy)
|
|
99
138
|
expect(@local_files_policy).to receive(:block_file_access?).and_return(true, true)
|
|
139
|
+
expect(TCellAgent::Cmdi).not_to receive(:parse_command_from_open)
|
|
100
140
|
end
|
|
101
141
|
end
|
|
102
142
|
|
|
103
|
-
it '
|
|
143
|
+
it 'executes OS commands', :skip_before do
|
|
104
144
|
result = Kernel.open('|echo test').read
|
|
105
145
|
expect(result).to eq "test\n"
|
|
106
146
|
|
|
107
147
|
result = open('|echo test').read
|
|
108
148
|
expect(result).to eq "test\n"
|
|
109
149
|
end
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
end.to raise_error(IOError)
|
|
150
|
+
it 'raises an IOError' do
|
|
151
|
+
expect do
|
|
152
|
+
Kernel.open(@new_file_name, 'w')
|
|
153
|
+
end.to raise_error(IOError)
|
|
115
154
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
end
|
|
155
|
+
expect do
|
|
156
|
+
open(@new_file_name, 'w')
|
|
157
|
+
end.to raise_error(IOError)
|
|
120
158
|
end
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
end.to raise_error(IOError)
|
|
159
|
+
it 'raises an IOError' do
|
|
160
|
+
expect do
|
|
161
|
+
Kernel.open(@new_file_name, 'w')
|
|
162
|
+
end.to raise_error(IOError)
|
|
126
163
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
end
|
|
164
|
+
expect do
|
|
165
|
+
open(@new_file_name, 'w')
|
|
166
|
+
end.to raise_error(IOError)
|
|
131
167
|
end
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
end.to raise_error(IOError)
|
|
168
|
+
it 'raises an IOError' do
|
|
169
|
+
expect do
|
|
170
|
+
Kernel.open(@new_file_name, 'a')
|
|
171
|
+
end.to raise_error(IOError)
|
|
137
172
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
end
|
|
173
|
+
expect do
|
|
174
|
+
open(@new_file_name, 'a')
|
|
175
|
+
end.to raise_error(IOError)
|
|
142
176
|
end
|
|
143
177
|
end
|
|
144
178
|
end
|
|
@@ -169,7 +203,7 @@ describe 'Kernel' do
|
|
|
169
203
|
end
|
|
170
204
|
end
|
|
171
205
|
context 'with a filename blocked for read/write' do
|
|
172
|
-
it '
|
|
206
|
+
it 'raises an IOError' do
|
|
173
207
|
expect(TCellAgent).to receive(:policy).with(
|
|
174
208
|
TCellAgent::PolicyTypes::LFI
|
|
175
209
|
).and_return(@local_files_policy, @local_files_policy)
|
|
@@ -196,7 +230,7 @@ describe 'Kernel' do
|
|
|
196
230
|
|
|
197
231
|
describe '::readline and #readline' do
|
|
198
232
|
context 'with a filename not blocked for read/write' do
|
|
199
|
-
it '
|
|
233
|
+
it 'reads the file' do
|
|
200
234
|
expect(TCellAgent).to receive(:policy).with(
|
|
201
235
|
TCellAgent::PolicyTypes::LFI
|
|
202
236
|
).and_return(@local_files_policy, @local_files_policy, @local_files_policy, @local_files_policy)
|
|
@@ -221,7 +255,7 @@ describe 'Kernel' do
|
|
|
221
255
|
end
|
|
222
256
|
end
|
|
223
257
|
context 'with a filename blocked for read' do
|
|
224
|
-
it '
|
|
258
|
+
it 'raises an IOError' do
|
|
225
259
|
expect(TCellAgent).to receive(:policy).with(
|
|
226
260
|
TCellAgent::PolicyTypes::LFI
|
|
227
261
|
).and_return(@local_files_policy, @local_files_policy)
|
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
|
3
3
|
module TCellAgent
|
|
4
4
|
module Instrumentation
|
|
5
5
|
module Lfi
|
|
6
|
-
describe '
|
|
6
|
+
describe '.extract_path_mode' do
|
|
7
7
|
context 'with path' do
|
|
8
8
|
it 'should extract the path correctly' do
|
|
9
9
|
args = '/path-to-file'
|
|
@@ -34,51 +34,91 @@ module TCellAgent
|
|
|
34
34
|
args = '/path-to-file', 'r'
|
|
35
35
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
36
36
|
expect(mode).to eq('Read')
|
|
37
|
+
|
|
38
|
+
args = '/path-to-file', { :mode => 'r' }
|
|
39
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
40
|
+
expect(mode).to eq('Read')
|
|
37
41
|
end
|
|
38
42
|
it 'should return Write for mode w' do
|
|
39
43
|
args = '/path-to-file', 'w'
|
|
40
44
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
41
45
|
expect(mode).to eq('Write')
|
|
46
|
+
|
|
47
|
+
args = '/path-to-file', { :mode => 'w' }
|
|
48
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
49
|
+
expect(mode).to eq('Write')
|
|
42
50
|
end
|
|
43
51
|
it 'should return Write for mode a' do
|
|
44
52
|
args = '/path-to-file', 'a'
|
|
45
53
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
46
54
|
expect(mode).to eq('Write')
|
|
55
|
+
|
|
56
|
+
args = '/path-to-file', { :mode => 'a' }
|
|
57
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
58
|
+
expect(mode).to eq('Write')
|
|
47
59
|
end
|
|
48
60
|
it 'should return ReadWrite for mode r+' do
|
|
49
61
|
args = '/path-to-file', 'r+'
|
|
50
62
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
51
63
|
expect(mode).to eq('ReadWrite')
|
|
64
|
+
|
|
65
|
+
args = '/path-to-file', { :mode => 'r+' }
|
|
66
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
67
|
+
expect(mode).to eq('ReadWrite')
|
|
52
68
|
end
|
|
53
69
|
it 'should return ReadWrite for mode w+' do
|
|
54
70
|
args = '/path-to-file', 'w+'
|
|
55
71
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
56
72
|
expect(mode).to eq('ReadWrite')
|
|
73
|
+
|
|
74
|
+
args = '/path-to-file', { :mode => 'w+' }
|
|
75
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
76
|
+
expect(mode).to eq('ReadWrite')
|
|
57
77
|
end
|
|
58
78
|
it 'should return ReadWrite for mode a+' do
|
|
59
79
|
args = '/path-to-file', 'a+'
|
|
60
80
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
61
81
|
expect(mode).to eq('ReadWrite')
|
|
82
|
+
|
|
83
|
+
args = '/path-to-file', { :mode => 'a+' }
|
|
84
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
85
|
+
expect(mode).to eq('ReadWrite')
|
|
62
86
|
end
|
|
63
87
|
it 'should return Read for mode ::File::RDONLY (0)' do
|
|
64
88
|
args = '/path-to-file', ::File::RDONLY
|
|
65
89
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
66
90
|
expect(mode).to eq('Read')
|
|
91
|
+
|
|
92
|
+
args = '/path-to-file', { :mode => ::File::RDONLY }
|
|
93
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
94
|
+
expect(mode).to eq('Read')
|
|
67
95
|
end
|
|
68
96
|
it 'should return Write for mode ::File::WRONLY (1)' do
|
|
69
97
|
args = '/path-to-file', ::File::WRONLY
|
|
70
98
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
71
99
|
expect(mode).to eq('Write')
|
|
100
|
+
|
|
101
|
+
args = '/path-to-file', { :mode => ::File::WRONLY }
|
|
102
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
103
|
+
expect(mode).to eq('Write')
|
|
72
104
|
end
|
|
73
105
|
it 'should return ReadWrite for mode ::File::RDWR (2)' do
|
|
74
106
|
args = '/path-to-file', ::File::RDWR
|
|
75
107
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
76
108
|
expect(mode).to eq('ReadWrite')
|
|
109
|
+
|
|
110
|
+
args = '/path-to-file', { :mode => ::File::RDWR }
|
|
111
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
112
|
+
expect(mode).to eq('ReadWrite')
|
|
77
113
|
end
|
|
78
114
|
it 'should return Write for mode ::File::CREAT | ::File::EXCL | ::File::WRONLY (2561)' do
|
|
79
115
|
args = '/path-to-file', ::File::CREAT | ::File::EXCL | ::File::WRONLY
|
|
80
116
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
81
117
|
expect(mode).to eq('Write')
|
|
118
|
+
|
|
119
|
+
args = '/path-to-file', { :mode => ::File::CREAT | ::File::EXCL | ::File::WRONLY }
|
|
120
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
121
|
+
expect(mode).to eq('Write')
|
|
82
122
|
end
|
|
83
123
|
end
|
|
84
124
|
context 'with an invalid mode' do
|
|
@@ -87,11 +127,16 @@ module TCellAgent
|
|
|
87
127
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
88
128
|
expect(mode).to eq('Read')
|
|
89
129
|
end
|
|
90
|
-
it 'should return Read when mode is
|
|
130
|
+
it 'should return Read when mode is an empty hash' do
|
|
91
131
|
args = '/path-to-file', {}
|
|
92
132
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
93
133
|
expect(mode).to eq('Read')
|
|
94
134
|
end
|
|
135
|
+
it 'should return Read when mode is a hash without a :mode key' do
|
|
136
|
+
args = '/path-to-file', { :placeholder => 'testing' }
|
|
137
|
+
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
138
|
+
expect(mode).to eq('Read')
|
|
139
|
+
end
|
|
95
140
|
it 'should return Read when mode is an array' do
|
|
96
141
|
args = '/path-to-file', []
|
|
97
142
|
_path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
|
|
@@ -100,6 +145,79 @@ module TCellAgent
|
|
|
100
145
|
end
|
|
101
146
|
end
|
|
102
147
|
end
|
|
148
|
+
|
|
149
|
+
describe '.raise_if_block' do
|
|
150
|
+
context 'when passed a blocked path' do
|
|
151
|
+
it 'raises an error' do
|
|
152
|
+
expect(TCellAgent::Instrumentation::Lfi).to receive(:block_file_access?).with(
|
|
153
|
+
'/blocked', 'Read'
|
|
154
|
+
).and_return(true)
|
|
155
|
+
|
|
156
|
+
expect do
|
|
157
|
+
TCellAgent::Instrumentation::Lfi.raise_if_block('/blocked', 'Read')
|
|
158
|
+
end.to raise_error(IOError)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
context 'when passed a path not blocked' do
|
|
162
|
+
it 'returns nil' do
|
|
163
|
+
expect(TCellAgent::Instrumentation::Lfi).to receive(:block_file_access?).with(
|
|
164
|
+
'/not-blocked', 'Read'
|
|
165
|
+
).and_return(false)
|
|
166
|
+
|
|
167
|
+
expect(TCellAgent::Instrumentation::Lfi.raise_if_block('/not-blocked', 'Read')).to eq nil
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
describe '.default_open_handler' do
|
|
173
|
+
it 'calls .raise_if_block' do
|
|
174
|
+
expect(TCellAgent::Instrumentation::Lfi).to receive(:raise_if_block).with(
|
|
175
|
+
'/placeholder', 'Read'
|
|
176
|
+
).and_return(nil)
|
|
177
|
+
|
|
178
|
+
expect(TCellAgent::Instrumentation::Lfi.default_open_handler(['/placeholder'], 'Read')).to eq nil
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it 'replaces the mode with override_mode' do
|
|
182
|
+
expect(TCellAgent::Instrumentation::Lfi).to receive(:extract_path_mode).with(
|
|
183
|
+
'/placeholder'
|
|
184
|
+
).and_return(['/placeholder', 'Read'])
|
|
185
|
+
expect(TCellAgent::Instrumentation::Lfi).to receive(:raise_if_block).with(
|
|
186
|
+
'/placeholder', 'ReadWrite'
|
|
187
|
+
).and_return(nil)
|
|
188
|
+
|
|
189
|
+
expect(TCellAgent::Instrumentation::Lfi.default_open_handler(['/placeholder'], 'ReadWrite')).to eq nil
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
describe '.argf_open_handler' do
|
|
194
|
+
it 'calls .extract_path_mode_argf' do
|
|
195
|
+
expect(TCellAgent::Instrumentation::Lfi).to receive(:extract_path_mode_argf).and_return(
|
|
196
|
+
['/placeholder', 'Read']
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
expect(TCellAgent::Instrumentation::Lfi.argf_open_handler).to eq nil
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
describe '.cmdi_open_handler' do
|
|
203
|
+
it 'behaves the similarly to default_open_handler' do
|
|
204
|
+
expect(TCellAgent::Instrumentation::Lfi).to receive(:raise_if_block).with(
|
|
205
|
+
'/placeholder', 'Read'
|
|
206
|
+
).and_return(nil)
|
|
207
|
+
|
|
208
|
+
expect(TCellAgent::Instrumentation::Lfi.default_open_handler(['/placeholder'], 'Read')).to eq nil
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'raises an error if command is blocked' do
|
|
212
|
+
expect(TCellAgent::Cmdi).to receive(:block_command?).with(
|
|
213
|
+
'ls'
|
|
214
|
+
).and_return(true)
|
|
215
|
+
|
|
216
|
+
expect do
|
|
217
|
+
TCellAgent::Instrumentation::Lfi.cmdi_open_handler('|ls')
|
|
218
|
+
end.to raise_error(RuntimeError)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
103
221
|
end
|
|
104
222
|
end
|
|
105
223
|
end
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
require 'spec_helper'
|
|
3
2
|
|
|
4
3
|
module TCellAgent
|
|
@@ -44,7 +43,7 @@ module TCellAgent
|
|
|
44
43
|
expect(@policy.enabled).to eq(true)
|
|
45
44
|
|
|
46
45
|
expect(
|
|
47
|
-
@policy.get_headers(@tcell_context)
|
|
46
|
+
@policy.get_headers('text/html', @tcell_context)
|
|
48
47
|
).to eq(
|
|
49
48
|
[{ 'name' => 'Content-Security-Policy',
|
|
50
49
|
'value' => "frame-ancestors 'none'; report-uri https://input.tcell-preview.io/csp/430d?sid=ab7074d0bf86c2884766d88b6ad9de4a&rid=route-id" }]
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
require 'spec_helper'
|
|
3
2
|
|
|
4
3
|
module TCellAgent
|
|
@@ -23,7 +22,7 @@ module TCellAgent
|
|
|
23
22
|
expect(native_agent).to_not receive(:get_headers)
|
|
24
23
|
|
|
25
24
|
tcell_context = double('tcell_context')
|
|
26
|
-
policy.get_headers(tcell_context)
|
|
25
|
+
policy.get_headers('text/html', tcell_context)
|
|
27
26
|
end
|
|
28
27
|
end
|
|
29
28
|
|
|
@@ -65,7 +64,7 @@ module TCellAgent
|
|
|
65
64
|
expect(@policy.enabled).to eq(true)
|
|
66
65
|
|
|
67
66
|
expect(
|
|
68
|
-
@policy.get_headers(@tcell_context)
|
|
67
|
+
@policy.get_headers('text/html', @tcell_context)
|
|
69
68
|
).to eq(
|
|
70
69
|
[{ 'name' => 'Content-Security-Policy', 'value' => 'test321' }]
|
|
71
70
|
)
|
|
@@ -92,7 +91,7 @@ module TCellAgent
|
|
|
92
91
|
expect(@policy.enabled).to eq(true)
|
|
93
92
|
|
|
94
93
|
expect(
|
|
95
|
-
@policy.get_headers(@tcell_context)
|
|
94
|
+
@policy.get_headers('text/html', @tcell_context)
|
|
96
95
|
).to eq(
|
|
97
96
|
[{ 'name' => 'Content-Security-Policy',
|
|
98
97
|
'value' => 'normalvalue; report-uri https://www.example.com/xys?sid=ab7074d0bf86c2884766d88b6ad9de4a&rid=route-id' }]
|
|
@@ -121,7 +120,7 @@ module TCellAgent
|
|
|
121
120
|
expect(@policy.enabled).to eq(true)
|
|
122
121
|
|
|
123
122
|
expect(
|
|
124
|
-
@policy.get_headers(@tcell_context)
|
|
123
|
+
@policy.get_headers('text/html', @tcell_context)
|
|
125
124
|
).to eq(
|
|
126
125
|
[{ 'name' => 'Content-Security-Policy',
|
|
127
126
|
'value' => 'normalvalue; report-uri https://www.example.com/1234567?sid=ab7074d0bf86c2884766d88b6ad9de4a&rid=route-id' }]
|
|
@@ -150,7 +149,7 @@ module TCellAgent
|
|
|
150
149
|
expect(@policy.enabled).to eq(true)
|
|
151
150
|
|
|
152
151
|
expect(
|
|
153
|
-
@policy.get_headers(@tcell_context)
|
|
152
|
+
@policy.get_headers('text/html', @tcell_context)
|
|
154
153
|
).to eq([])
|
|
155
154
|
end
|
|
156
155
|
end
|
|
@@ -78,6 +78,8 @@ module TCellAgent
|
|
|
78
78
|
meta_data = TCellAgent::Tests::MetaDataBuilder.new.update_attribute(
|
|
79
79
|
'remote_address', nil
|
|
80
80
|
).build
|
|
81
|
+
expect(@native_agent).to receive(:apply_suspicious_quick_check).with(any_args)
|
|
82
|
+
expect(@native_agent).not_to receive(:apply_patches).with(any_args)
|
|
81
83
|
resp = @policy.block_request?(meta_data)
|
|
82
84
|
expect(resp).to eq(false)
|
|
83
85
|
end
|
|
@@ -88,6 +90,8 @@ module TCellAgent
|
|
|
88
90
|
meta_data = TCellAgent::Tests::MetaDataBuilder.new.update_attribute(
|
|
89
91
|
'remote_address', ''
|
|
90
92
|
).build
|
|
93
|
+
expect(@native_agent).to receive(:apply_suspicious_quick_check).with(any_args)
|
|
94
|
+
expect(@native_agent).not_to receive(:apply_patches).with(any_args)
|
|
91
95
|
resp = @policy.block_request?(meta_data)
|
|
92
96
|
expect(resp).to eq(false)
|
|
93
97
|
end
|
|
@@ -98,20 +102,35 @@ module TCellAgent
|
|
|
98
102
|
meta_data = TCellAgent::Tests::MetaDataBuilder.new.update_attribute(
|
|
99
103
|
'remote_address', '2.2.2.2'
|
|
100
104
|
).build
|
|
105
|
+
expect(@native_agent).to receive(:apply_suspicious_quick_check).with(any_args)
|
|
106
|
+
expect(@native_agent).not_to receive(:apply_patches).with(any_args)
|
|
101
107
|
resp = @policy.block_request?(meta_data)
|
|
102
108
|
expect(resp).to eq(false)
|
|
103
109
|
end
|
|
104
110
|
end
|
|
105
111
|
|
|
106
|
-
context 'request comes from
|
|
107
|
-
it 'should
|
|
112
|
+
context 'request comes from blocked ip' do
|
|
113
|
+
it 'should block request' do
|
|
108
114
|
meta_data = TCellAgent::Tests::MetaDataBuilder.new.update_attribute(
|
|
109
115
|
'remote_address', '1.1.1.1'
|
|
110
116
|
).build
|
|
117
|
+
expect(@native_agent).to receive(:apply_suspicious_quick_check).with(any_args).and_return(2)
|
|
118
|
+
expect(@native_agent).not_to receive(:apply_patches).with(any_args)
|
|
111
119
|
resp = @policy.block_request?(meta_data)
|
|
112
120
|
expect(resp).to eq(true)
|
|
113
121
|
end
|
|
114
122
|
end
|
|
123
|
+
|
|
124
|
+
context 'request comes from suspcious ip' do
|
|
125
|
+
it 'should call apply_patches' do
|
|
126
|
+
meta_data = TCellAgent::Tests::MetaDataBuilder.new.update_attribute(
|
|
127
|
+
'remote_address', '1.1.1.1'
|
|
128
|
+
).build
|
|
129
|
+
expect(@native_agent).to receive(:apply_suspicious_quick_check).with(any_args).and_return(1)
|
|
130
|
+
expect(@native_agent).to receive(:apply_patches).with(any_args).and_return('Blocked Response')
|
|
131
|
+
@policy.block_request?(meta_data)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
115
134
|
end
|
|
116
135
|
end
|
|
117
136
|
end
|
|
@@ -6,7 +6,7 @@ module TCellAgent
|
|
|
6
6
|
assert_policy_state = proc do |policies, state|
|
|
7
7
|
expect(policies.keys.size).to eq(10)
|
|
8
8
|
|
|
9
|
-
policies.
|
|
9
|
+
policies.each_value do |policy|
|
|
10
10
|
next if policy.instance_of?(TCellAgent::Policies::LoginPolicy)
|
|
11
11
|
next if policy.instance_of?(TCellAgent::Policies::SystemEnablements)
|
|
12
12
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
require 'spec_helper'
|
|
3
2
|
|
|
4
3
|
module TCellAgent
|
|
@@ -16,13 +15,7 @@ module TCellAgent
|
|
|
16
15
|
).update_attribute(
|
|
17
16
|
'route_id', 'route-id'
|
|
18
17
|
).build
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
after(:each) do
|
|
22
|
-
TCellAgent::Rust::NativeAgent.free_agent(@native_agent.agent_ptr)
|
|
23
|
-
end
|
|
24
18
|
|
|
25
|
-
it 'should return csp header' do
|
|
26
19
|
enablements = @native_agent.update_policies(
|
|
27
20
|
{
|
|
28
21
|
'secure-headers' => {
|
|
@@ -41,14 +34,26 @@ module TCellAgent
|
|
|
41
34
|
|
|
42
35
|
@policy = HeadersPolicy.new(@native_agent, enablements)
|
|
43
36
|
expect(@policy.enabled).to eq(true)
|
|
37
|
+
end
|
|
44
38
|
|
|
39
|
+
after(:each) do
|
|
40
|
+
TCellAgent::Rust::NativeAgent.free_agent(@native_agent.agent_ptr)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'should return csp header' do
|
|
45
44
|
expect(
|
|
46
|
-
@policy.get_headers(@tcell_context)
|
|
45
|
+
@policy.get_headers('text/html', @tcell_context)
|
|
47
46
|
).to eq(
|
|
48
47
|
[{ 'name' => 'X-Content-Type-Options',
|
|
49
48
|
'value' => 'nosniff' }]
|
|
50
49
|
)
|
|
51
50
|
end
|
|
51
|
+
|
|
52
|
+
it 'should not return csp header on json' do
|
|
53
|
+
expect(
|
|
54
|
+
@policy.get_headers('application/json', @tcell_context)
|
|
55
|
+
).to eq([])
|
|
56
|
+
end
|
|
52
57
|
end
|
|
53
58
|
end
|
|
54
59
|
end
|