Skip to content

Commit 9eca3a0

Browse files
committed
Impersonation spec
1 parent 10029ee commit 9eca3a0

File tree

2 files changed

+99
-8
lines changed

2 files changed

+99
-8
lines changed

lib/msf/core/post/windows/mssql.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ def run_cmd(cmd, token = true)
136136
# @param [Hash] service the service to target
137137
# @return [Boolean] true if impersonated successfully
138138
def impersonate_sql_user(service)
139+
return false if service.nil? || service[:pid].nil? || service[:pid] <= 0
140+
139141
pid = service[:pid]
140142
vprint_status("Current user: #{session.sys.config.getuid}")
141143
current_privs = client.sys.config.getprivs
@@ -150,6 +152,8 @@ def impersonate_sql_user(service)
150152
end
151153
end
152154

155+
return false unless username
156+
153157
session.core.use('incognito') unless session.incognito
154158
vprint_status("Attemping to impersonate user: #{username}")
155159
res = session.incognito.incognito_impersonate_token(username)

spec/lib/msf/core/post/windows/mssql_spec.rb

Lines changed: 95 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
let(:subject) do
88
mod = Module.new
99
mod.extend described_class
10-
stubs = [ :vprint_status, :print_status, :vprint_good, :print_good, :print_error ]
10+
stubs = [ :vprint_status, :print_status, :vprint_good, :print_good, :print_error, :print_warning ]
1111
stubs.each { |meth| mod.stub(meth) }
1212
mod.stub(:service_info).and_return({})
1313
mod
@@ -235,8 +235,8 @@
235235
end
236236

237237
it "should identify only a named SQL instance" do
238-
allow(subject).to receive(:each_service).and_yield(normal_service).and_yield(running_analysis_service).
239-
and_yield(running_2k_sql_instance).and_yield(running_named_2k_sql_instance)
238+
allow(subject).to receive(:each_service).and_yield(normal_service).and_yield(running_analysis_service)
239+
.and_yield(running_2k_sql_instance).and_yield(running_named_2k_sql_instance)
240240
result = subject.check_for_sqlserver(instance)
241241
result.should eq running_named_2k_sql_instance
242242
end
@@ -248,8 +248,8 @@
248248
end
249249

250250
it "should identify only a named SQL instance" do
251-
allow(subject).to receive(:each_service).and_yield(normal_service).and_yield(running_analysis_service).
252-
and_yield(running_2k5_sql_instance).and_yield(running_named_2k5_sql_instance)
251+
allow(subject).to receive(:each_service).and_yield(normal_service).and_yield(running_analysis_service)
252+
.and_yield(running_2k5_sql_instance).and_yield(running_named_2k5_sql_instance)
253253
result = subject.check_for_sqlserver(instance)
254254
result.should eq running_named_2k5_sql_instance
255255
end
@@ -261,14 +261,102 @@
261261
end
262262

263263
it "should identify only a named SQL instance" do
264-
allow(subject).to receive(:each_service).and_yield(normal_service).and_yield(running_analysis_service).
265-
and_yield(running_2k8_sql_instance).and_yield(running_named_2k8_sql_instance)
264+
allow(subject).to receive(:each_service).and_yield(normal_service).and_yield(running_analysis_service)
265+
.and_yield(running_2k8_sql_instance).and_yield(running_named_2k8_sql_instance)
266266
result = subject.check_for_sqlserver(instance)
267267
result.should eq running_named_2k8_sql_instance
268268
end
269269
end
270270
end
271271

272+
describe "#impersonate_sql_user" do
273+
let(:pid) do
274+
8787
275+
end
276+
277+
let(:user) do
278+
'sqluser'
279+
end
280+
281+
let(:service) do
282+
{ pid: pid }
283+
end
284+
285+
let(:process) do
286+
{ 'pid' => pid, 'user' => user }
287+
end
288+
289+
it 'should return false if service is invalid or pid is invalid' do
290+
subject.impersonate_sql_user(nil).should be_falsey
291+
subject.impersonate_sql_user(pid: nil).should be_falsey
292+
subject.impersonate_sql_user(pid: 0).should be_falsey
293+
end
294+
295+
context 'user has privs to impersonate' do
296+
before(:each) do
297+
subject.stub_chain('session.sys.config.getuid').and_return('Superman')
298+
subject.stub_chain('client.sys.config.getprivs').and_return(['SeAssignPrimaryTokenPrivilege'])
299+
subject.stub_chain('session.incognito').and_return(true)
300+
subject.stub_chain('session.sys.process.each_process').and_yield(process)
301+
end
302+
303+
it 'should return true if successful impersonating' do
304+
subject.stub_chain('session.incognito.incognito_impersonate_token').with(user).and_return('Successfully')
305+
subject.impersonate_sql_user(service).should be true
306+
end
307+
308+
it 'should return false if fails impersonating' do
309+
subject.stub_chain('session.incognito.incognito_impersonate_token').with(user).and_return('guff')
310+
subject.impersonate_sql_user(service).should be false
311+
end
312+
313+
it 'should return false if unable to find process username' do
314+
subject.stub_chain('session.sys.process.each_process').and_yield('pid' => 0)
315+
subject.impersonate_sql_user(service).should be false
316+
end
317+
end
318+
319+
context 'user does not have privs to impersonate' do
320+
before(:each) do
321+
subject.stub_chain('session.sys.config.getuid').and_return('Superman')
322+
subject.stub_chain('client.sys.config.getprivs').and_return([])
323+
end
324+
325+
it 'should return true if successful' do
326+
expect(subject).to receive(:print_warning)
327+
subject.stub_chain('session.core.migrate').with(pid).and_return(true)
328+
subject.impersonate_sql_user(service).should be true
329+
end
330+
331+
it 'should rescue an exception if migration fails' do
332+
expect(subject).to receive(:print_warning)
333+
subject.stub_chain('session.core.migrate').with(pid).and_raise(Rex::RuntimeError)
334+
subject.impersonate_sql_user(service).should be false
335+
end
336+
end
337+
end
338+
339+
describe "#get_system" do
340+
it 'should return true if already SYSTEM' do
341+
expect(subject).to receive(:is_system?).and_return(true)
342+
subject.get_system.should be_truthy
343+
end
344+
345+
it 'should return true if able to get SYSTEM and print a warning' do
346+
expect(subject).to receive(:is_system?).and_return(false)
347+
expect(subject).to receive(:print_warning)
348+
subject.stub_chain('session.priv.getsystem').and_return([true])
349+
subject.get_system.should be_truthy
350+
end
351+
352+
it 'should return false if unable to get SYSTEM and print a warning' do
353+
expect(subject).to receive(:is_system?).and_return(false)
354+
expect(subject).to receive(:print_warning)
355+
subject.stub_chain('session.priv.getsystem').and_return([false])
356+
subject.get_system.should be_falsey
357+
end
358+
end
359+
272360
describe "#run_cmd" do
273361
it 'should return a string' do
274362
p = double('process')
@@ -377,7 +465,6 @@
377465
expect(subject).to receive(:run_cmd).and_return('SQL Server Command Line Tool')
378466
subject.check_sqlcmd.should be_truthy
379467
end
380-
381468
end
382469

383470
describe "#get_sql_client" do

0 commit comments

Comments
 (0)