From f26c14f05ab7aecb995567be75a0f24dfd93d6b5 Mon Sep 17 00:00:00 2001 From: cgranleese-r7 Date: Thu, 11 Sep 2025 15:15:55 +0100 Subject: [PATCH] Address PR feedback --- .../framework/login_scanner/postgres.rb | 23 +++++++++++++++---- lib/metasploit/framework/tcp/client.rb | 5 ---- lib/postgres/postgres-pr/connection.rb | 7 +++--- .../framework/login_scanner/postgres_spec.rb | 5 ++-- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/postgres.rb b/lib/metasploit/framework/login_scanner/postgres.rb index 1047b7203a..468a248505 100644 --- a/lib/metasploit/framework/login_scanner/postgres.rb +++ b/lib/metasploit/framework/login_scanner/postgres.rb @@ -1,6 +1,4 @@ require 'metasploit/framework/login_scanner/base' -require 'metasploit/framework/login_scanner/rex_socket' -require 'metasploit/framework/tcp/client' require 'postgres_msf' module Metasploit @@ -12,8 +10,25 @@ module Metasploit # and attempting them. It then saves the results. class Postgres include Metasploit::Framework::LoginScanner::Base - include Metasploit::Framework::LoginScanner::RexSocket - include Metasploit::Framework::Tcp::Client + + # @!attribute ssl + # @return [Boolean] Whether the connection should use SSL + attr_accessor :ssl + # @!attribute ssl_version + # @return [String] The version of SSL to implement + attr_accessor :ssl_version + # @!attribute ssl_verify_mode + # @return [String] the SSL certification verification mechanism + attr_accessor :ssl_verify_mode + # @!attribute ssl_cipher + # @return [String] The SSL cipher to use for the context + attr_accessor :ssl_cipher + # @!attribute max_send_size + # @return [Integer] The max size of the data to encapsulate in a single packet + attr_accessor :max_send_size + # @!attribute send_delay + # @return [Integer] The delay between sending packets + attr_accessor :send_delay # @returns [Boolean] If a login is successful and this attribute is true - a Msf::Db::PostgresPR::Connection instance is used as proof, # and the socket is not immediately closed diff --git a/lib/metasploit/framework/tcp/client.rb b/lib/metasploit/framework/tcp/client.rb index 16759fda79..ae03c04bb5 100644 --- a/lib/metasploit/framework/tcp/client.rb +++ b/lib/metasploit/framework/tcp/client.rb @@ -80,11 +80,6 @@ module Metasploit dossl = ssl end - # For Postgres, always connect with SSL disabled; SSL is enabled after the initial connection is made - if defined?(self) && self.class.name =~ /Postgres/ - dossl = false - end - nsock = Rex::Socket::Tcp.create( 'PeerHost' => opts['RHOST'] || rhost, 'PeerHostname' => opts['SSLServerNameIndication'] || opts['RHOSTNAME'], diff --git a/lib/postgres/postgres-pr/connection.rb b/lib/postgres/postgres-pr/connection.rb index 96596980b7..80ed5fc0df 100644 --- a/lib/postgres/postgres-pr/connection.rb +++ b/lib/postgres/postgres-pr/connection.rb @@ -358,13 +358,14 @@ class Connection 'Proxies' => proxies ) if ssl - # Send SSLRequest packet - ssl_request = [8, 80877103].pack('N2') - @conn.write(ssl_request) + ssl_request_message = SSLRequest.new(80877103) + @conn.write(ssl_request_message.dump) response = @conn.read(1) if response == 'S' ssl_context = OpenSSL::SSL::SSLContext.new ssl_socket = OpenSSL::SSL::SSLSocket.new(@conn, ssl_context) + # Ensure the underlying TCP socket is closed when the SSL socket is closed + # This prevents resource leaks and ensures proper cleanup of the connection ssl_socket.sync_close = true ssl_socket.connect @conn = ssl_socket diff --git a/spec/lib/metasploit/framework/login_scanner/postgres_spec.rb b/spec/lib/metasploit/framework/login_scanner/postgres_spec.rb index 22edb948f7..e761605f70 100644 --- a/spec/lib/metasploit/framework/login_scanner/postgres_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/postgres_spec.rb @@ -5,6 +5,7 @@ RSpec.describe Metasploit::Framework::LoginScanner::Postgres do let(:public) { 'root' } let(:private) { 'toor' } let(:realm) { 'template1' } + let(:host) { '127.0.0.1' } let(:full_cred) { Metasploit::Framework::Credential.new( @@ -23,7 +24,7 @@ RSpec.describe Metasploit::Framework::LoginScanner::Postgres do ) } - subject(:login_scanner) { described_class.new } + subject(:login_scanner) { described_class.new(host: host) } it_behaves_like 'Metasploit::Framework::LoginScanner::Base', has_realm_key: true, has_default_realm: true @@ -40,7 +41,7 @@ RSpec.describe Metasploit::Framework::LoginScanner::Postgres do context 'when there is no realm on the credential' do it 'uses template1 as the default realm' do - expect(Msf::Db::PostgresPR::Connection).to receive(:new).with('template1', 'root', 'toor', 'tcp://:', nil, nil) + expect(Msf::Db::PostgresPR::Connection).to receive(:new).with('template1', 'root', 'toor', 'tcp://127.0.0.1:5432', nil, nil) login_scanner.attempt_login(cred_no_realm) end end