From 1991a4c0e030f2390d95aa4c86d0dd162d2cbc4b Mon Sep 17 00:00:00 2001 From: sjanusz-r7 Date: Thu, 28 Mar 2024 12:30:34 +0000 Subject: [PATCH] Add MySQL Arch & Platform detection by query --- lib/msf/base/sessions/mysql.rb | 7 ++++++ lib/msf/core/module/platform.rb | 2 +- lib/rex/proto/mysql/client.rb | 22 +++++++++++++++++++ spec/lib/msf/base/sessions/mysql_spec.rb | 10 +++++++++ .../console/command_dispatcher/core_spec.rb | 2 ++ 5 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/msf/base/sessions/mysql.rb b/lib/msf/base/sessions/mysql.rb index 5e1f445abfd88..065f8c2091310 100644 --- a/lib/msf/base/sessions/mysql.rb +++ b/lib/msf/base/sessions/mysql.rb @@ -9,6 +9,13 @@ class Msf::Sessions::MySQL < Msf::Sessions::Sql def initialize(rstream, opts = {}) @client = opts.fetch(:client) self.console = ::Rex::Post::MySQL::Ui::Console.new(self) + + server_version_vars = @client.query_server_version_vars + unless server_version_vars.empty? + self.arch = server_version_vars.fetch(:arch, nil) + self.platform = server_version_vars.fetch(:platform, nil) + end + super(rstream, opts) end diff --git a/lib/msf/core/module/platform.rb b/lib/msf/core/module/platform.rb index eb5de28c00fc7..36030756af3b7 100644 --- a/lib/msf/core/module/platform.rb +++ b/lib/msf/core/module/platform.rb @@ -383,7 +383,7 @@ class Ruby < Msf::Module::Platform # class Linux < Msf::Module::Platform Rank = 100 - Alias = "linux" + Aliases = [ 'linux', 'debian-linux-gnu' ] end # diff --git a/lib/rex/proto/mysql/client.rb b/lib/rex/proto/mysql/client.rb index 31ac3311e927b..1bbb0ff270837 100644 --- a/lib/rex/proto/mysql/client.rb +++ b/lib/rex/proto/mysql/client.rb @@ -28,6 +28,28 @@ def current_database # Current database is stored as an array under the type 1 key. session_track.fetch(1, ['']).first end + + # @return [Hash] A hash with :arch and :version keys if the query was successful, otherwise empty. + def query_server_version_vars + result = {} + + # Get the current platform & arch by querying the server. + server_vars = query("show variables where variable_name like 'version%'").entries + server_vars.each do |server_var| + name, value = server_var + + case name + when 'version_compile_machine' + result[:arch] = value + when 'version_compile_os' + result[:platform] = value + else + next + end + end + + result + end end end end diff --git a/spec/lib/msf/base/sessions/mysql_spec.rb b/spec/lib/msf/base/sessions/mysql_spec.rb index 47ce65e03a7e4..6abeeca866d40 100644 --- a/spec/lib/msf/base/sessions/mysql_spec.rb +++ b/spec/lib/msf/base/sessions/mysql_spec.rb @@ -19,6 +19,7 @@ let(:port) { '3306' } let(:peerinfo) { "#{address}:#{port}" } let(:current_database) { 'database_name' } + let(:server_version_vars) { { arch: 'x86_64', platform: 'Linux' } } before(:each) do allow(user_input).to receive(:output=) @@ -26,6 +27,7 @@ allow(rstream).to receive(:peerinfo).and_return(peerinfo) allow(client).to receive(:socket).and_return(rstream) allow(client).to receive(:current_database).and_return(current_database) + allow(client).to receive(:query_server_version_vars).and_return(server_version_vars) allow(::Rex::Proto::MySQL::Client).to receive(:connect).and_return(client) end @@ -78,6 +80,14 @@ it 'creates a new console' do expect(subject.console).to be_a(console_class) end + + it 'gets the correct arch' do + expect(subject.arch).to eq('x86_64') + end + + it 'gets the correct platform' do + expect(subject.platform).to eq('Linux') + end end describe '#bootstrap' do diff --git a/spec/lib/rex/post/mysql/ui/console/command_dispatcher/core_spec.rb b/spec/lib/rex/post/mysql/ui/console/command_dispatcher/core_spec.rb index ef49374997463..64e3d32acbd47 100644 --- a/spec/lib/rex/post/mysql/ui/console/command_dispatcher/core_spec.rb +++ b/spec/lib/rex/post/mysql/ui/console/command_dispatcher/core_spec.rb @@ -17,11 +17,13 @@ console.disable_output = true console end + let(:server_version_vars) { { arch: 'x86_64', platform: 'Linux' } } before(:each) do allow(rstream).to receive(:peerinfo).and_return(peerinfo) allow(client).to receive(:current_database).and_return(current_database) allow(client).to receive(:socket).and_return(rstream) + allow(client).to receive(:query_server_version_vars).and_return(server_version_vars) allow(session).to receive(:console).and_return(console) allow(session).to receive(:name).and_return('test client name') allow(session).to receive(:sid).and_return('test client sid')