Skip to content

Commit

Permalink
Land #19022, Add MySQL Arch & Platform detection by query
Browse files Browse the repository at this point in the history
  • Loading branch information
cgranleese-r7 authored Apr 10, 2024
2 parents 2346bfe + a862b16 commit 53efed1
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 3 deletions.
2 changes: 2 additions & 0 deletions lib/msf/base/sessions/mysql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class Msf::Sessions::MySQL < Msf::Sessions::Sql
# @param [Hash] opts
def initialize(rstream, opts = {})
@client = opts.fetch(:client)
self.platform = opts.fetch(:platform)
self.arch = opts.fetch(:arch)
self.console = ::Rex::Post::MySQL::Ui::Console.new(self)
super(rstream, opts)
end
Expand Down
61 changes: 61 additions & 0 deletions lib/rex/proto/mysql/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,67 @@ def current_database
# Current database is stored as an array under the type 1 key.
session_track.fetch(1, ['']).first
end

# 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?

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

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

platform.realname
end

def map_compile_arch_to_architecture(compile_arch)
return '' if compile_arch.blank?

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

if compile_arch.match?('sparc')
if compile_arch.include?('64')
arch = ARCH_SPARC64
else
arch = ARCH_SPARC
end
elsif compile_arch.match?('arm')
arch = ARCH_AARCH64
elsif compile_arch.match?('64')
arch = ARCH_X86_64
elsif compile_arch.match?('86') || compile_arch.match?('i686')
arch = ARCH_X86
else
arch = ''
end

arch
end

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

server_vars = query("show variables where variable_name in ('version_compile_machine', 'version_compile_os')").entries.to_h
result[:arch] = map_compile_arch_to_architecture(server_vars['version_compile_machine'])
result[:platform] = map_compile_os_to_platform(server_vars['version_compile_os'])

result
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/scanner/mysql/mysql_login.rb
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def int_version(str)
def session_setup(result)
return unless (result.connection && result.proof)

my_session = Msf::Sessions::MySQL.new(result.connection, { client: result.proof })
my_session = Msf::Sessions::MySQL.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/mysql_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

RSpec.describe Msf::Sessions::MySQL do
let(:client) { instance_double(::Rex::Proto::MySQL::Client) }
let(:opts) { { client: client } }
let(:opts) { { client: client, platform: Msf::Platform::Linux.realname, arch: ARCH_X86_64 } }
let(:console_class) { Rex::Post::MySQL::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 @@ -10,7 +10,7 @@
let(:address) { '192.0.2.1' }
let(:port) { '3306' }
let(:peerinfo) { "#{address}:#{port}" }
let(:session) { Msf::Sessions::MySQL.new(nil, { client: client }) }
let(:session) { Msf::Sessions::MySQL.new(nil, { client: client, platform: Msf::Platform::Linux.realname, arch: ARCH_X86_64 }) }
let(:console) do
console = Rex::Post::MySQL::Ui::Console.new(session)
console.disable_output = true
Expand Down
45 changes: 45 additions & 0 deletions spec/lib/rex/proto/mysql/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,49 @@
end
end
end

describe '#map_compile_os_to_platform' do
[
{ info: 'linux', expected: Msf::Platform::Linux.realname },
{ info: 'linux2.6', expected: Msf::Platform::Linux.realname },
{ info: 'debian-linux-gnu', expected: Msf::Platform::Linux.realname },
{ info: 'win', expected: Msf::Platform::Windows.realname },
{ info: 'windows', expected: Msf::Platform::Windows.realname },
{ info: 'darwin', expected: Msf::Platform::OSX.realname },
{ info: 'osx', expected: Msf::Platform::OSX.realname },
{ 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 },
].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: 'x86_64', expected: ARCH_X86_64 },
{ info: 'x86_x64', expected: ARCH_X86_64 },
{ info: 'x64', expected: ARCH_X86_64 },
{ info: '64', expected: ARCH_X86_64 },
{ info: 'x86', expected: ARCH_X86 },
{ info: '86', expected: ARCH_X86 },
{ info: 'i686', expected: ARCH_X86 },
{ info: 'arm64', expected: ARCH_AARCH64 },
{ info: 'arm', expected: ARCH_AARCH64 },
{ info: 'sparc', expected: ARCH_SPARC },
{ info: 'sparc64', expected: ARCH_SPARC64 },
{ info: '', expected: '' },
{ info: 'blank', expected: '' },
{ info: nil, expected: '' },
].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
end

0 comments on commit 53efed1

Please sign in to comment.