Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add arch and platform detection for mssql sessions #19112

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -71,7 +71,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
Loading