Skip to content

Commit b423241

Browse files
committed
Use Rex Post MySQL Client for lib, specs & modules
1 parent 55a8d67 commit b423241

File tree

11 files changed

+47
-48
lines changed

11 files changed

+47
-48
lines changed

lib/metasploit/framework/login_scanner/mysql.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
require 'metasploit/framework/tcp/client'
2-
require 'mysql'
32
require 'metasploit/framework/login_scanner/base'
43
require 'metasploit/framework/login_scanner/rex_socket'
54
require 'rex/proto/mysql/client'
@@ -47,22 +46,22 @@ def attempt_login(credential)
4746
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT,
4847
proof: e
4948
})
50-
rescue Mysql::ClientError => e
49+
rescue Rex::Proto::MySQL::Client::ClientError => e
5150
result_options.merge!({
5251
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT,
5352
proof: e
5453
})
55-
rescue Mysql::HostNotPrivileged => e
54+
rescue Rex::Proto::MySQL::Client::HostNotPrivileged => e
5655
result_options.merge!({
5756
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT,
5857
proof: e
5958
})
60-
rescue Mysql::AccessDeniedError => e
59+
rescue Rex::Proto::MySQL::Client::AccessDeniedError => e
6160
result_options.merge!({
6261
status: Metasploit::Model::Login::Status::INCORRECT,
6362
proof: e
6463
})
65-
rescue Mysql::HostIsBlocked => e
64+
rescue Rex::Proto::MySQL::Client::HostIsBlocked => e
6665
result_options.merge!({
6766
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT,
6867
proof: e

lib/msf/core/exploit/remote/mysql.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ module Exploit::Remote::MYSQL
2020
include Exploit::Remote::Tcp
2121

2222
# @!attribute [rw] mysql_conn
23-
# @return [::Mysql]
23+
# @return [::Rex::Proto::MySQL::Client]
2424
attr_accessor :mysql_conn
2525

2626
def initialize(info = {})
@@ -48,16 +48,16 @@ def mysql_login(user='root', pass='', db=nil)
4848
rescue Errno::ECONNREFUSED
4949
print_error("Connection refused")
5050
return false
51-
rescue ::Mysql::ClientError
51+
rescue ::Rex::Proto::MySQL::Client::ClientError
5252
print_error("Connection timedout")
5353
return false
5454
rescue Errno::ETIMEDOUT
5555
print_error("Operation timedout")
5656
return false
57-
rescue ::Mysql::HostNotPrivileged
57+
rescue ::Rex::Proto::MySQL::Client::HostNotPrivileged
5858
print_error("Unable to login from this host due to policy")
5959
return false
60-
rescue ::Mysql::AccessDeniedError
60+
rescue ::Rex::Proto::MySQL::Client::AccessDeniedError
6161
print_error("Access denied")
6262
return false
6363
end
@@ -87,7 +87,7 @@ def mysql_login_datastore
8787
def mysql_query(sql)
8888
begin
8989
res = mysql_conn.query(sql)
90-
rescue ::Mysql::Error => e
90+
rescue ::Rex::Proto::MySQL::Client::Error => e
9191
print_error("MySQL Error: #{e.class} #{e.to_s}")
9292
return nil
9393
rescue Rex::ConnectionTimeout => e

modules/auxiliary/scanner/mysql/mysql_authbypass_hashdump.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ def run_host(ip)
7070

7171
print_good "#{rhost}:#{rport} The server accepted our first login as #{username} with a bad password. URI: mysql://#{username}:#{password}@#{rhost}:#{rport}"
7272

73-
rescue ::Mysql::HostNotPrivileged
73+
rescue ::Rex::Proto::MySQL::Client::HostNotPrivileged
7474
print_error "#{rhost}:#{rport} Unable to login from this host due to policy (may still be vulnerable)"
7575
return
76-
rescue ::Mysql::AccessDeniedError
76+
rescue ::Rex::Proto::MySQL::Client::AccessDeniedError
7777
print_good "#{rhost}:#{rport} The server allows logins, proceeding with bypass test"
7878
rescue ::Interrupt
7979
raise $!
@@ -125,7 +125,7 @@ def run_host(ip)
125125
print_good "#{rhost}:#{rport} Successfully bypassed authentication after #{count} attempts. URI: mysql://#{username}:#{password}@#{rhost}:#{rport}"
126126
results << mysql_client
127127
close_required = false
128-
rescue ::Mysql::AccessDeniedError
128+
rescue ::Rex::Proto::MySQL::Client::AccessDeniedError
129129
rescue ::Exception => e
130130
print_bad "#{rhost}:#{rport} Thread #{count}] caught an unhandled exception: #{e}"
131131
ensure

modules/auxiliary/scanner/mysql/mysql_file_enum.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def run_host(ip)
5656

5757
begin
5858
mysql_query_no_handle("USE " + datastore['DATABASE_NAME'])
59-
rescue ::Mysql::Error => e
59+
rescue ::Rex::Proto::MySQL::Client::Error => e
6060
vprint_error("MySQL Error: #{e.class} #{e.to_s}")
6161
return
6262
rescue Rex::ConnectionTimeout => e
@@ -87,7 +87,7 @@ def run_host(ip)
8787
def check_dir dir
8888
begin
8989
res = mysql_query_no_handle("LOAD DATA INFILE '" + dir + "' INTO TABLE " + datastore['TABLE_NAME'])
90-
rescue ::Mysql::TextfileNotReadable
90+
rescue ::Rex::Proto::MySQL::Client::TextfileNotReadable
9191
print_good("#{dir} is a directory and exists")
9292
report_note(
9393
:host => mysql_conn.host,
@@ -97,7 +97,7 @@ def check_dir dir
9797
:proto => 'tcp',
9898
:update => :unique_data
9999
)
100-
rescue ::Mysql::DataTooLong, ::Mysql::TruncatedWrongValueForField
100+
rescue ::Rex::Proto::MySQL::Client::DataTooLong, ::Rex::Proto::MySQL::Client::TruncatedWrongValueForField
101101
print_good("#{dir} is a file and exists")
102102
report_note(
103103
:host => mysql_conn.host,
@@ -107,9 +107,9 @@ def check_dir dir
107107
:proto => 'tcp',
108108
:update => :unique_data
109109
)
110-
rescue ::Mysql::ServerError
110+
rescue ::Rex::Proto::MySQL::Client::ServerError
111111
vprint_warning("#{dir} does not exist")
112-
rescue ::Mysql::Error => e
112+
rescue ::Rex::Proto::MySQL::Client::Error => e
113113
vprint_error("MySQL Error: #{e.class} #{e.to_s}")
114114
return
115115
rescue Rex::ConnectionTimeout => e

modules/auxiliary/scanner/mysql/mysql_login.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ def int_version(str)
179179
end
180180

181181
# @param [Metasploit::Framework::LoginScanner::Result] result
182-
# @param [::Mysql] client
182+
# @param [::Rex::Proto::MySQL::Client] client
183183
# @return [Msf::Sessions::MySQL]
184184
def session_setup(result, client)
185185
return unless (result && client)

modules/auxiliary/scanner/mysql/mysql_writable_dirs.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def check_dir(dir)
6262
begin
6363
print_status("Checking #{dir}...")
6464
res = mysql_query_no_handle("SELECT _utf8'test' INTO DUMPFILE '#{dir}/" + datastore['FILE_NAME'] + "'")
65-
rescue ::Mysql::ServerError => e
65+
rescue ::Rex::Proto::MySQL::Client::ServerError => e
6666
print_warning(e.to_s)
6767
rescue Rex::ConnectionTimeout => e
6868
print_error("Timeout: #{e.message}")

modules/exploits/windows/mysql/mysql_mof.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def query(q)
6767
res.each_hash do |row|
6868
rows << row
6969
end
70-
rescue ::Mysql::ParseError
70+
rescue ::Rex::Proto::MySQL::Client::ParseError
7171
return rows
7272
end
7373

@@ -102,7 +102,7 @@ def exploit
102102
m = mysql_login(datastore['USERNAME'], datastore['PASSWORD'])
103103
return unless m
104104
end
105-
rescue ::Mysql::AccessDeniedError
105+
rescue ::Rex::Proto::MySQL::Client::AccessDeniedError
106106
print_error("Access denied.")
107107
return
108108
end
@@ -120,7 +120,7 @@ def exploit
120120
begin
121121
upload_file(exe, dest)
122122
register_file_for_cleanup("#{exe_name}")
123-
rescue ::Mysql::AccessDeniedError
123+
rescue ::Rex::Proto::MySQL::Client::AccessDeniedError
124124
print_error("No permission to write. I blame kc :-)")
125125
return
126126
end
@@ -132,7 +132,7 @@ def exploit
132132
begin
133133
upload_file(mof, dest)
134134
register_file_for_cleanup("wbem\\mof\\good\\#{mof_name}")
135-
rescue ::Mysql::AccessDeniedError
135+
rescue ::Rex::Proto::MySQL::Client::AccessDeniedError
136136
print_error("No permission to write. Bail!")
137137
return
138138
end

modules/exploits/windows/mysql/mysql_start_up.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def query(q)
7373
res.each_hash do |row|
7474
rows << row
7575
end
76-
rescue ::Mysql::ParseError
76+
rescue ::Rex::Proto::MySQL::Client::ParseError
7777
return rows
7878
end
7979

@@ -113,7 +113,7 @@ def exploit
113113
m = mysql_login(datastore['USERNAME'], datastore['PASSWORD'])
114114
return unless m
115115
end
116-
rescue ::Mysql::AccessDeniedError
116+
rescue ::Rex::Proto::MySQL::Client::AccessDeniedError
117117
fail_with(Failure::NoAccess, "#{peer} - Access denied")
118118
end
119119

@@ -125,7 +125,7 @@ def exploit
125125

126126
begin
127127
drive = get_drive_letter
128-
rescue ::Mysql::ParseError
128+
rescue ::Rex::Proto::MySQL::Client::ParseError
129129
fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine drive name")
130130
end
131131

@@ -138,7 +138,7 @@ def exploit
138138
print_status("Uploading to '#{dest}'")
139139
begin
140140
upload_file(exe, dest)
141-
rescue ::Mysql::AccessDeniedError
141+
rescue ::Rex::Proto::MySQL::Client::AccessDeniedError
142142
fail_with(Failure::NotVulnerable, "#{peer} - No permission to write. I blame kc :-)")
143143
end
144144
register_file_for_cleanup("#{dest}")

spec/lib/metasploit/framework/login_scanner/mysql_spec.rb

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
RSpec.describe Metasploit::Framework::LoginScanner::MySQL do
55
let(:public) { 'root' }
66
let(:private) { 'toor' }
7-
let(:client) { instance_double(::Mysql) }
7+
let(:client) { instance_double(::Rex::Proto::MySQL::Client) }
88
let(:pub_blank) {
99
Metasploit::Framework::Credential.new(
1010
paired: true,
@@ -42,69 +42,69 @@
4242

4343
context 'when the attempt is successful' do
4444
it 'returns a result object with a status of Metasploit::Model::Login::Status::SUCCESSFUL' do
45-
expect(::Mysql).to receive(:connect).and_return(client)
45+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_return(client)
4646
expect(login_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::SUCCESSFUL
4747
end
4848
end
4949

5050
context 'when the attempt is unsuccessful' do
5151
context 'due to connection refused' do
5252
it 'returns a result with a status of Metasploit::Model::Login::Status::UNABLE_TO_CONNECT' do
53-
expect(::Mysql).to receive(:connect).and_raise Errno::ECONNREFUSED
53+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_raise Errno::ECONNREFUSED
5454
expect(login_scanner.attempt_login(pub_pub).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
5555
end
5656

5757
it 'returns a result with the proof containing an appropriate error message' do
58-
expect(::Mysql).to receive(:connect).and_raise Errno::ECONNREFUSED
58+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_raise Errno::ECONNREFUSED
5959
expect(login_scanner.attempt_login(pub_pub).proof).to be_a(Errno::ECONNREFUSED)
6060
end
6161
end
6262

6363
context 'due to connection timeout' do
6464
it 'returns a result with a status of Metasploit::Model::Login::Status::UNABLE_TO_CONNECT' do
65-
expect(::Mysql).to receive(:connect).and_raise Mysql::ClientError, "Client Error"
65+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_raise ::Rex::Proto::MySQL::Client::ClientError, "Client Error"
6666
expect(login_scanner.attempt_login(pub_pub).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
6767
end
6868

6969
it 'returns a result with the proof containing an appropriate error message' do
70-
expect(::Mysql).to receive(:connect).and_raise Mysql::ClientError, "Client Error"
71-
expect(login_scanner.attempt_login(pub_pub).proof).to be_a(Mysql::ClientError)
70+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_raise ::Rex::Proto::MySQL::Client::ClientError, "Client Error"
71+
expect(login_scanner.attempt_login(pub_pub).proof).to be_a(::Rex::Proto::MySQL::Client::ClientError)
7272
end
7373
end
7474

7575
context 'due to operation timeout' do
7676
it 'returns a result with a status of Metasploit::Model::Login::Status::UNABLE_TO_CONNECT' do
77-
expect(::Mysql).to receive(:connect).and_raise Errno::ETIMEDOUT
77+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_raise Errno::ETIMEDOUT
7878
expect(login_scanner.attempt_login(pub_pub).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
7979
end
8080

8181
it 'returns a result with the proof containing an appropriate error message' do
82-
expect(::Mysql).to receive(:connect).and_raise Errno::ETIMEDOUT
82+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_raise Errno::ETIMEDOUT
8383
expect(login_scanner.attempt_login(pub_pub).proof).to be_a(Errno::ETIMEDOUT)
8484
end
8585
end
8686

8787
context 'due to not being allowed to connect from this host' do
8888
it 'returns a result with a status of Metasploit::Model::Login::Status::UNABLE_TO_CONNECT' do
89-
expect(::Mysql).to receive(:connect).and_raise Mysql::HostNotPrivileged, "Host not privileged"
89+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_raise Rex::Proto::MySQL::Client::HostNotPrivileged, "Host not privileged"
9090
expect(login_scanner.attempt_login(pub_pub).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
9191
end
9292

9393
it 'returns a result with the proof containing an appropriate error message' do
94-
expect(::Mysql).to receive(:connect).and_raise Mysql::HostNotPrivileged, "Host not privileged"
95-
expect(login_scanner.attempt_login(pub_pub).proof).to be_a(Mysql::HostNotPrivileged)
94+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_raise Rex::Proto::MySQL::Client::HostNotPrivileged, "Host not privileged"
95+
expect(login_scanner.attempt_login(pub_pub).proof).to be_a(Rex::Proto::MySQL::Client::HostNotPrivileged)
9696
end
9797
end
9898

9999
context 'due to access denied' do
100100
it 'returns a result with a status of Metasploit::Model::Login::Status::INCORRECT' do
101-
expect(::Mysql).to receive(:connect).and_raise Mysql::AccessDeniedError, "Access Denied"
101+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_raise Rex::Proto::MySQL::Client::AccessDeniedError, "Access Denied"
102102
expect(login_scanner.attempt_login(pub_pub).status).to eq Metasploit::Model::Login::Status::INCORRECT
103103
end
104104

105105
it 'returns a result with the proof containing an appropriate error message' do
106-
expect(::Mysql).to receive(:connect).and_raise Mysql::AccessDeniedError, "Access Denied"
107-
expect(login_scanner.attempt_login(pub_pub).proof).to be_a(Mysql::AccessDeniedError)
106+
expect(::Rex::Proto::MySQL::Client).to receive(:connect).and_raise Rex::Proto::MySQL::Client::AccessDeniedError, "Access Denied"
107+
expect(login_scanner.attempt_login(pub_pub).proof).to be_a(Rex::Proto::MySQL::Client::AccessDeniedError)
108108
end
109109
end
110110
end

spec/lib/msf/base/sessions/mysql_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# frozen_string_literal: true
22

33
require 'spec_helper'
4-
require 'mysql'
4+
require 'rex/proto/mysql/client'
55

66
RSpec.describe Msf::Sessions::MySQL do
77
let(:rstream) { instance_double(::Rex::Socket) }
8-
let(:client) { instance_double(::Mysql) }
8+
let(:client) { instance_double(::Rex::Proto::MySQL::Client) }
99
let(:opts) { { client: client } }
1010
let(:console_class) { Rex::Post::MySQL::Ui::Console }
1111
let(:user_input) { instance_double(Rex::Ui::Text::Input::Readline) }
@@ -26,7 +26,7 @@
2626
allow(rstream).to receive(:peerinfo).and_return(peerinfo)
2727
allow(client).to receive(:socket).and_return(rstream)
2828
allow(client).to receive(:database).and_return(database)
29-
allow(::Mysql).to receive(:connect).and_return(client)
29+
allow(::Rex::Proto::MySQL::Client).to receive(:connect).and_return(client)
3030
end
3131

3232
subject(:session) do

0 commit comments

Comments
 (0)