Files
metasploit-gs/lib/msf/core/exploit/remote/mssql.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

231 lines
6.1 KiB
Ruby
Raw Normal View History

# -*- coding: binary -*-
2023-12-12 09:53:37 -06:00
require 'rex/proto/mssql/client'
require 'metasploit/framework/tcp/client'
2005-11-26 11:16:50 +00:00
module Msf
###
#
# This module exposes methods for querying a remote MSSQL service
#
###
module Exploit::Remote::MSSQL
include Exploit::Remote::MSSQL_COMMANDS
2005-11-26 11:16:50 +00:00
include Exploit::Remote::Udp
include Exploit::Remote::Tcp
include Exploit::Remote::NTLM::Client
include Msf::Exploit::Remote::Kerberos::Ticket::Storage
include Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::Options
2013-08-30 16:28:33 -05:00
2024-02-13 13:00:38 -06:00
attr_accessor :mssql_client
2005-11-26 11:16:50 +00:00
#
# Creates an instance of a MSSQL exploit module.
#
def initialize(info = {})
super
2013-08-30 16:28:33 -05:00
# Register the options that all MSSQL exploits may make use of.
2005-11-26 11:16:50 +00:00
register_options(
[
Opt::RHOST,
Opt::RPORT(1433),
2010-01-20 01:43:01 +00:00
OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']),
OptString.new('PASSWORD', [ false, 'The password for the specified username', '']),
2023-09-24 17:42:00 -04:00
OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]),
2023-12-12 09:53:37 -06:00
# OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - TODO: support TDS Encryption
2010-01-20 01:43:01 +00:00
], Msf::Exploit::Remote::MSSQL)
register_advanced_options(
[
2012-02-03 12:14:37 -07:00
OptPath.new('HEX2BINARY', [ false, "The path to the hex2binary script on the disk",
2013-09-26 20:34:48 +01:00
File.join(Msf::Config.data_directory, "exploits", "mssql", "h2b")
2012-02-03 12:14:37 -07:00
]),
OptString.new('DOMAIN', [ true, 'The domain to use for windows authentication', 'WORKSTATION'], aliases: ['MssqlDomain']),
*kerberos_storage_options(protocol: 'Mssql'),
*kerberos_auth_options(protocol: 'Mssql', auth_methods: Msf::Exploit::Remote::AuthOption::MSSQL_OPTIONS),
2011-09-07 19:32:16 +00:00
], Msf::Exploit::Remote::MSSQL)
2010-01-20 02:31:30 +00:00
register_autofilter_ports([ 1433, 1434, 1435, 14330, 2533, 9152, 2638 ])
register_autofilter_services(%W{ ms-sql-s ms-sql2000 sybase })
2005-11-26 11:16:50 +00:00
end
2013-08-30 16:28:33 -05:00
2024-02-12 15:47:49 -06:00
def set_session(client)
print_status("Using existing session #{session.sid}")
@mssql_client = client
end
2005-11-26 11:16:50 +00:00
#
# This method sends a UDP query packet to the server and
# parses out the reply packet into a hash
#
def mssql_ping(timeout=5)
2005-11-26 11:16:50 +00:00
data = { }
2013-08-30 16:28:33 -05:00
2005-11-26 11:16:50 +00:00
ping_sock = Rex::Socket::Udp.create(
'PeerHost' => rhost,
2005-11-26 11:16:50 +00:00
'PeerPort' => 1434,
'Context' =>
{
'Msf' => framework,
'MsfExploit' => self,
})
2013-08-30 16:28:33 -05:00
2005-11-26 11:16:50 +00:00
ping_sock.put("\x02")
resp, _saddr, _sport = ping_sock.recvfrom(65535, timeout)
2005-11-26 11:16:50 +00:00
ping_sock.close
2013-08-30 16:28:33 -05:00
2005-11-26 11:16:50 +00:00
return data if not resp
return data if resp.length == 0
2013-08-30 16:28:33 -05:00
return mssql_ping_parse(resp)
end
2013-08-30 16:28:33 -05:00
#
# Parse a 'ping' response and format as a hash
#
def mssql_ping_parse(data)
res = []
var = nil
idx = data.index('ServerName')
return res if not idx
sdata = data[idx, (data.length - 1)]
2013-08-30 16:28:33 -05:00
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
2005-11-26 11:16:50 +00:00
end
res << rinst
end
2013-08-30 16:28:33 -05:00
return res
2005-11-26 11:16:50 +00:00
end
2013-08-30 16:28:33 -05:00
2009-10-18 20:58:01 +00:00
#
# Execute a system command via xp_cmdshell
#
2023-12-12 09:53:37 -06:00
def mssql_parse_tds_reply(data, info)
@mssql_client.mssql_parse_tds_reply(data, info)
end
2013-08-30 16:28:33 -05:00
2023-12-12 09:53:37 -06:00
def mssql_parse_reply(data, info)
@mssql_client.mssql_parse_reply(data, info)
2009-10-18 20:58:01 +00:00
end
2013-08-30 16:28:33 -05:00
2009-10-18 20:58:01 +00:00
#
2023-12-12 09:53:37 -06:00
# Parse a single row of a TDS reply
2009-10-18 20:58:01 +00:00
#
2023-12-12 09:53:37 -06:00
def mssql_parse_tds_row(data, info)
@mssql_client.mssql_parse_tds_row(data, info)
end
2013-08-30 16:28:33 -05:00
2023-12-12 09:53:37 -06:00
#
# Parse a "ret" TDS token
#
def mssql_parse_ret(data, info)
@mssql_client.mssql_parse_ret(data, info)
end
2013-08-30 16:28:33 -05:00
2023-12-12 09:53:37 -06:00
#
# Parse a "done" TDS token
#
def mssql_parse_done(data, info)
@mssql_client.mssql_parse_done(data, info)
end
2013-08-30 16:28:33 -05:00
2023-12-12 09:53:37 -06:00
#
# Parse an "error" TDS token
#
def mssql_parse_error(data, info)
@mssql_client.mssql_parse_error(data, info)
end
2013-08-30 16:28:33 -05:00
2023-12-12 09:53:37 -06:00
#
# Parse an "environment change" TDS token
#
def mssql_parse_env(data, info)
@mssql_client.mssql_parse_env(data, info)
end
2013-08-30 16:28:33 -05:00
2023-12-12 09:53:37 -06:00
#
# Parse an "information" TDS token
#
def mssql_parse_info(data, info)
@mssql_client.mssql_parse_info(data, info)
end
2013-08-30 16:28:33 -05:00
2023-12-12 09:53:37 -06:00
def mssql_xpcmdshell(cmd, doprint=false, opts={})
@mssql_client.mssql_xpcmdshell(cmd, doprint, opts)
2009-10-18 20:58:01 +00:00
end
2013-08-30 16:28:33 -05:00
2023-12-12 09:53:37 -06:00
#
# Upload and execute a Windows binary through MSSQL queries
#
def mssql_upload_exec(exe, debug=false)
@mssql_client.mssql_upload_exec(exe, debug)
end
2013-08-30 16:28:33 -05:00
#
# Upload and execute a Windows binary through MSSQL queries and Powershell
#
def powershell_upload_exec(exe, debug=false)
2023-12-12 09:53:37 -06:00
@mssql_client.powershell_upload_exec(exe, debug)
end
2013-08-30 16:28:33 -05:00
#
#this method send a prelogin packet and check if encryption is off
#
def mssql_prelogin(enc_error=false)
2023-12-12 09:53:37 -06:00
@mssql_client.mssql_prelogin(enc_error)
end
2013-08-30 16:28:33 -05:00
2005-11-26 11:16:50 +00:00
#
# 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
#
2023-12-12 09:53:37 -06:00
def mssql_login(user='sa', pass='', db='', domain_name='')
@mssql_client ||= Rex::Proto::MSSQL::Client.new(self, framework, datastore['RHOST'], datastore['RPORT'])
result = @mssql_client.mssql_login(user, pass, db, domain_name)
add_socket(@mssql_client.sock) if @mssql_client.sock && !sockets.include?(@mssql_client.sock)
result
end
2023-12-12 09:53:37 -06:00
def mssql_login_datastore(db=nil)
mssql_login(datastore['USERNAME'], datastore['PASSWORD'], db || datastore['DATABASE'] || '', datastore['MssqlDomain'] || '')
end
2009-10-18 20:58:01 +00:00
#
# Issue a SQL query using the TDS protocol
#
def mssql_query(sqla, doprint=false, opts={})
2024-02-06 11:43:44 +00:00
@mssql_client.query(sqla, doprint, opts)
end
2009-10-18 20:58:01 +00:00
#
# Nicely print the results of a SQL query
#
def mssql_print_reply(info)
2023-12-12 09:53:37 -06:00
@mssql_client.mssql_print_reply(info)
end
2023-12-12 09:53:37 -06:00
def mssql_send_recv(req, timeout=15, check_status = true)
@mssql_client.mssql_send_recv(req, timeout, check_status)
end
2013-08-30 16:28:33 -05:00
2023-12-12 09:53:37 -06:00
#
# 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*")
2009-01-12 05:18:05 +00:00
end
end
2005-11-26 11:16:50 +00:00
end