Skip to content

Commit

Permalink
Land #19112, add arch and platform detection for mssql sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
cgranleese-r7 authored Apr 19, 2024
2 parents 939f433 + 0c6af95 commit aa3181c
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 16 deletions.
2 changes: 2 additions & 0 deletions lib/msf/base/sessions/mssql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class Msf::Sessions::MSSQL < Msf::Sessions::Sql

def initialize(rstream, opts = {})
@client = opts.fetch(:client)
self.platform = opts.fetch(:platform)
self.arch = opts.fetch(:arch)
self.console = ::Rex::Post::MSSQL::Ui::Console.new(self, opts)

super(rstream, opts)
Expand Down
51 changes: 51 additions & 0 deletions lib/rex/proto/mssql/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,57 @@ def initialize(framework_module, framework, rhost, rport = 1433, proxies = nil)
@current_database = ''
end

# MS SQL Server only supports Windows and Linux
def map_compile_os_to_platform(server_info)
return '' if server_info.blank?

os_data = server_info.downcase.encode(::Encoding::BINARY)

if os_data.match?('linux')
platform = Msf::Platform::Linux.realname
elsif os_data.match?('windows')
platform = Msf::Platform::Windows.realname
elsif os_data.match?('win')
platform = Msf::Platform::Windows.realname
else
platform = os_data
end
platform
end

# MS SQL Server currently only supports 64 bit but older installs may be x86
def map_compile_arch_to_architecture(server_info)
return '' if server_info.blank?

arch_data = server_info.downcase.encode(::Encoding::BINARY)

if arch_data.match?('x64')
arch = ARCH_X86_64
elsif arch_data.match?('x86')
arch = ARCH_X86
elsif arch_data.match?('64')
arch = ARCH_X86_64
elsif arch_data.match?('32-bit')
arch = ARCH_X86
else
arch = arch_data
end
arch
end

# @return [Hash] Detect the platform and architecture of the MSSQL server:
# * :arch [String] The server architecture.
# * :platform [String] The server platform.
def detect_platform_and_arch
result = {}

server_vars = query('select @@version')[:rows][0][0]

result[:arch] = map_compile_arch_to_architecture(server_vars)
result[:platform] = map_compile_os_to_platform(server_vars)
result
end

#
# This method connects to the server over TCP and attempts
# to authenticate with the supplied username and password
Expand Down
18 changes: 9 additions & 9 deletions lib/rex/proto/mysql/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,25 @@ def current_database
# List of supported MySQL platforms & architectures:
# https://www.mysql.com/support/supportedplatforms/database.html
def map_compile_os_to_platform(compile_os)
return Msf::Platform::Unknown.realname if compile_os.blank?
return '' if compile_os.blank?

compile_os = compile_os.downcase.encode(::Encoding::BINARY)

if compile_os.match?('linux')
platform = Msf::Platform::Linux
platform = Msf::Platform::Linux.realname
elsif compile_os.match?('unix')
platform = Msf::Platform::Unix
platform = Msf::Platform::Unix.realname
elsif compile_os.match?(/(darwin|mac|osx)/)
platform = Msf::Platform::OSX
platform = Msf::Platform::OSX.realname
elsif compile_os.match?('win')
platform = Msf::Platform::Windows
platform = Msf::Platform::Windows.realname
elsif compile_os.match?('solaris')
platform = Msf::Platform::Solaris
platform = Msf::Platform::Solaris.realname
else
platform = Msf::Platform::Unknown
platform = compile_os
end

platform.realname
platform
end

def map_compile_arch_to_architecture(compile_arch)
Expand All @@ -75,7 +75,7 @@ def map_compile_arch_to_architecture(compile_arch)
elsif compile_arch.match?('86') || compile_arch.match?('i686')
arch = ARCH_X86
else
arch = ''
arch = compile_arch
end

arch
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/scanner/mssql/mssql_login.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def run_host(ip)
def session_setup(result)
return unless (result.connection && result.proof)

my_session = Msf::Sessions::MSSQL.new(result.connection, { client: result.proof })
my_session = Msf::Sessions::MSSQL.new(result.connection, { client: result.proof, **result.proof.detect_platform_and_arch })
merge_me = {
'USERPASS_FILE' => nil,
'USER_FILE' => nil,
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/msf/base/sessions/mssql_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

RSpec.describe Msf::Sessions::MSSQL do
let(:client) { instance_double(Rex::Proto::MSSQL::Client) }
let(:opts) { { client: client } }
let(:opts) { { client: client, platform: Msf::Platform::Linux.realname, arch: ARCH_X86_64 } }
let(:console_class) { Rex::Post::MSSQL::Ui::Console }
let(:user_input) { instance_double(Rex::Ui::Text::Input::Readline) }
let(:user_output) { instance_double(Rex::Ui::Text::Output::Stdio) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

RSpec.describe Rex::Post::MSSQL::Ui::Console::CommandDispatcher::Core do
let(:client) { instance_double(Rex::Proto::MSSQL::Client) }
let(:session) { Msf::Sessions::MSSQL.new(nil, { client: client }) }
let(:session) { Msf::Sessions::MSSQL.new(nil, { client: client, platform: Msf::Platform::Linux.realname, arch: ARCH_X86_64 }) }
let(:address) { '192.0.2.1' }
let(:port) { '1433' }
let(:peer_info) { "#{address}:#{port}" }
Expand Down
40 changes: 40 additions & 0 deletions spec/lib/rex/proto/mssql/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,46 @@

it_behaves_like 'session compatible SQL client'

describe '#map_compile_os_to_platform' do
[
{ info: 'linux', expected: Msf::Platform::Linux.realname },
{ info: 'windows', expected: Msf::Platform::Windows.realname },
{ info: 'win', expected: Msf::Platform::Windows.realname },
].each do |test|
it "correctly identifies '#{test[:info]}' as '#{test[:expected]}'" do
expect(subject.map_compile_os_to_platform(test[:info])).to eq(test[:expected])
end
end
end

describe '#map_compile_arch_to_architecture' do
[
{ info: 'x64', expected: ARCH_X86_64 },
{ info: 'x86', expected: ARCH_X86 },
{ info: '64', expected: ARCH_X86_64 },
{ info: '32-bit', expected: ARCH_X86 },
].each do |test|
it "correctly identifies '#{test[:info]}' as '#{test[:expected]}'" do
expect(subject.map_compile_arch_to_architecture(test[:info])).to eq(test[:expected])
end
end
end

describe '#detect_platform_and_arch' do
[
{ version: 'Microsoft SQL Server 2022 (RTM-CU12) (KB5033663) - 16.0.4115.5 (X64) Mar 4 2024 08:56:10 Copyright (C) 2022 Microsoft Corporation Developer Edition (64-bit) on Linux (Ubuntu 22.04.4 LTS) <X64>', expected: { arch: 'x86_64', platform: 'Linux' } },
{ version: 'Microsoft SQL Server 2022 (RTM) - 16.0.1000.6 (X64) Oct 8 2022 05:58:25 Copyright (C) 2022 Microsoft Corporation Developer Edition (64-bit) on Windows Server 2022 Standard 10.0 <X64> (Build 20348: ) (Hypervisor)', expected: { arch: 'x86_64', platform: 'Windows' } },
].each do |test|
context "when the database is version #{test[:version]}" do
it "returns #{test[:expected]}" do
mock_query_result = { rows: [[test[:version]]] }
allow(subject).to receive(:query).with('select @@version').and_return(mock_query_result)

expect(subject.detect_platform_and_arch).to eq test[:expected]
end
end
end
end
describe '#current_database' do
context 'we have not selected a database yet' do
subject do
Expand Down
8 changes: 4 additions & 4 deletions spec/lib/rex/proto/mysql/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
{ info: 'macos', expected: Msf::Platform::OSX.realname },
{ info: 'unix', expected: Msf::Platform::Unix.realname },
{ info: 'solaris', expected: Msf::Platform::Solaris.realname },
{ info: '', expected: Msf::Platform::Unknown.realname },
{ info: 'blank', expected: Msf::Platform::Unknown.realname },
{ info: nil, expected: Msf::Platform::Unknown.realname },
{ info: '', expected: '' },
{ info: 'blank', expected: 'blank' },
{ info: nil, expected: '' },
].each do |test|
it "correctly identifies '#{test[:info]}' as '#{test[:expected]}'" do
expect(subject.map_compile_os_to_platform(test[:info])).to eq(test[:expected])
Expand All @@ -69,7 +69,7 @@
{ info: 'sparc', expected: ARCH_SPARC },
{ info: 'sparc64', expected: ARCH_SPARC64 },
{ info: '', expected: '' },
{ info: 'blank', expected: '' },
{ info: 'blank', expected: 'blank' },
{ info: nil, expected: '' },
].each do |test|
it "correctly identifies '#{test[:info]}' as '#{test[:expected]}'" do
Expand Down

0 comments on commit aa3181c

Please sign in to comment.