Path: blob/master/lib/metasploit/framework/login_scanner/postgres.rb
28052 views
require 'metasploit/framework/login_scanner/base'1require 'postgres_msf'23module Metasploit4module Framework5module LoginScanner67# This is the LoginScanner class for dealing with PostgreSQL database servers.8# It is responsible for taking a single target, and a list of credentials9# and attempting them. It then saves the results.10class Postgres11include Metasploit::Framework::LoginScanner::Base1213# @!attribute ssl14# @return [Boolean] Whether the connection should use SSL15attr_accessor :ssl16# @!attribute ssl_version17# @return [String] The version of SSL to implement18attr_accessor :ssl_version19# @!attribute ssl_verify_mode20# @return [String] the SSL certification verification mechanism21attr_accessor :ssl_verify_mode22# @!attribute ssl_cipher23# @return [String] The SSL cipher to use for the context24attr_accessor :ssl_cipher25# @!attribute max_send_size26# @return [Integer] The max size of the data to encapsulate in a single packet27attr_accessor :max_send_size28# @!attribute send_delay29# @return [Integer] The delay between sending packets30attr_accessor :send_delay3132# @returns [Boolean] If a login is successful and this attribute is true - a Msf::Db::PostgresPR::Connection instance is used as proof,33# and the socket is not immediately closed34attr_accessor :use_client_as_proof3536DEFAULT_PORT = 543237DEFAULT_REALM = 'template1'38LIKELY_PORTS = [ DEFAULT_PORT ]39LIKELY_SERVICE_NAMES = [ 'postgres' ]40PRIVATE_TYPES = [ :password ]41REALM_KEY = Metasploit::Model::Realm::Key::POSTGRESQL_DATABASE4243# This method attempts a single login with a single credential against the target44# @param credential [Credential] The credential object to attempt to login with45# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object46def attempt_login(credential)47result_options = {48credential: credential,49host: host,50port: port,51protocol: 'tcp',52service_name: 'postgres'53}5455db_name = credential.realm || 'template1'5657if ::Rex::Socket.is_ipv6?(host)58uri = "tcp://[#{host}]:#{port}"59else60uri = "tcp://#{host}:#{port}"61end6263pg_conn = nil6465begin66ssl_opts = {}67ssl_opts[:ssl_version] = ssl_version if ssl_version68ssl_opts[:ssl_verify_mode] = ssl_verify_mode if ssl_verify_mode69ssl_opts[:ssl_cipher] = ssl_cipher if ssl_cipher7071pg_conn = Msf::Db::PostgresPR::Connection.new(72db_name,73credential.public,74credential.private,75uri,76proxies,77ssl,78ssl_opts79)80rescue ::RuntimeError => e81case e.to_s.split("\t")[1]82when "C3D000"83result_options.merge!({84status: Metasploit::Model::Login::Status::INCORRECT,85proof: "C3D000, Creds were good but database was bad"86})87when "C28000", "C28P01"88result_options.merge!({89status: Metasploit::Model::Login::Status::INCORRECT,90proof: "Invalid username or password"91})92else93result_options.merge!({94status: Metasploit::Model::Login::Status::INCORRECT,95proof: e.message96})97end98rescue Rex::ConnectionError, Rex::ConnectionProxyError, Errno::ECONNRESET, Errno::EINTR, Errno::ENOTCONN, Rex::TimeoutError, EOFError, Timeout::Error => e99result_options.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)100rescue Msf::Db::PostgresPR::AuthenticationMethodMismatch => e101result_options.merge!({102status: Metasploit::Model::Login::Status::INCORRECT,103proof: e.message104})105end106107if pg_conn108result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL109110# This module no longer owns the socket so return it as proof so the calling context can perform additional operations111# Additionally assign values to nil to avoid closing the socket etc automatically112if use_client_as_proof113result_options[:proof] = pg_conn114result_options[:connection] = pg_conn.conn115else116pg_conn.close117end118else119result_options[:status] = Metasploit::Model::Login::Status::INCORRECT120end121122::Metasploit::Framework::LoginScanner::Result.new(result_options)123end124125def set_sane_defaults126self.connection_timeout ||= 30127self.port ||= DEFAULT_PORT128self.max_send_size ||= 0129self.send_delay ||= 0130end131132end133end134end135end136137138