Skip to content

Commit

Permalink
Merge pull request #615 from Jan-E/php-mailer-5.2.19
Browse files Browse the repository at this point in the history
Fixed issue #12020: Critical Vulnerability in PHPMailer
  • Loading branch information
lacrioque committed Dec 27, 2016
2 parents 226bde2 + 31f2fb7 commit 450397e
Show file tree
Hide file tree
Showing 21 changed files with 595 additions and 436 deletions.
12 changes: 12 additions & 0 deletions application/third_party/phpmailer/.gitattributes
@@ -0,0 +1,12 @@
* text=auto

/docs export-ignore
/test export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.scrutinizer.yml export-ignore
/.travis.yml export-ignore
/travis.phpunit.xml.dist export-ignore
/SECURITY.md export-ignore
/changelog.md export-ignore
/README.md export-ignore
1 change: 1 addition & 0 deletions application/third_party/phpmailer/.travis.yml
@@ -1,5 +1,6 @@
language: php
php:
- 7.1
- 7.0
- 5.6
- 5.5
Expand Down
10 changes: 10 additions & 0 deletions application/third_party/phpmailer/README.md
Expand Up @@ -139,6 +139,16 @@ Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.svg)](h

If this isn't passing, is there something you can do to help?

## Security

Please disclose any vulnerabilities found responsibly - report any security problems found to the maintainers privately.

PHPMailer versions prior to 5.2.14 (released November 2015) are vulnerable to [CVE-2015-8476](https://web.nvd.nist.gov/view/vuln/detail?vulnId=) an SMTP CRLF injection bug permitting arbitrary message sending.

PHPMailer versions prior to 5.2.10 (released May 2015) are vulnerable to [CVE-2008-5619](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2008-5619), a remote code execution vulnerability in the bundled html2text library. This file was removed in 5.2.10, so if you are using a version prior to that and make use of the html2text function, it's vitally important that you upgrade and remove this file.

See [SECURITY](https://github.com/PHPMailer/PHPMailer/tree/master/SECURITY) for older security issues.

## Contributing

Please submit bug reports, suggestions and pull requests to the [GitHub issue tracker](https://github.com/PHPMailer/PHPMailer/issues).
Expand Down
20 changes: 20 additions & 0 deletions application/third_party/phpmailer/SECURITY.md
@@ -0,0 +1,20 @@
# Security notices relating to PHPMailer

Please disclose any vulnerabilities found responsibly - report any security problems found to the maintainers privately.

PHPMailer versions prior to 5.2.18 (released December 2016) are vulnerable to [CVE-2016-10033](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-10033) a remote code execution vulnerability, responsibly reported by [Dawid Golunski](https://legalhackers.com).

PHPMailer versions prior to 5.2.14 (released November 2015) are vulnerable to [CVE-2015-8476](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-8476) an SMTP CRLF injection bug permitting arbitrary message sending.

PHPMailer versions prior to 5.2.10 (released May 2015) are vulnerable to [CVE-2008-5619](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2008-5619), a remote code execution vulnerability in the bundled html2text library. This file was removed in 5.2.10, so if you are using a version prior to that and make use of the html2text function, it's vitally important that you upgrade and remove this file.

PHPMailer versions prior to 2.0.7 and 2.2.1 are vulnerable to [CVE-2012-0796](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2012-0796), an email header injection attack.

Joomla 1.6.0 uses PHPMailer in an unsafe way, allowing it to reveal local file paths, reported in [CVE-2011-3747](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2011-3747).

PHPMailer didn't sanitise the `$lang_path` parameter in `SetLanguage`. This wasn't a problem in itself, but some apps (PHPClassifieds, ATutor) also failed to sanitise user-provided parameters passed to it, permitting semi-arbitrary local file inclusion, reported in [CVE-2010-4914](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2010-4914), [CVE-2007-2021](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2007-2021) and [CVE-2006-5734](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2006-5734).

PHPMailer 1.7.2 and earlier contained a possible DDoS vulnerability reported in [CVE-2005-1807](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-1807).

PHPMailer 1.7 and earlier (June 2003) have a possible vulnerability in the `SendmailSend` method where shell commands may not be sanitised. Reported in [CVE-2007-3215](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2007-3215).

2 changes: 1 addition & 1 deletion application/third_party/phpmailer/VERSION
@@ -1 +1 @@
5.2.16
5.2.19
21 changes: 21 additions & 0 deletions application/third_party/phpmailer/changelog.md
@@ -1,5 +1,26 @@
# ChangeLog

## Version 5.2.19 (December 26th 2016)
* Minor cleanup

## Version 5.2.18 (December 24th 2016)
* **SECURITY** Critical security update for CVE-2016-10033 please update now! Thanks to [Dawid Golunski](https://legalhackers.com).
* Add ability to extract the SMTP transaction ID from some common SMTP success messages
* Minor documentation tweaks

## Version 5.2.17 (December 9th 2016)
* This is officially the last feature release of 5.2. Security fixes only from now on; use PHPMailer 6.0!
* Allow DKIM private key to be provided as a string
* Provide mechanism to allow overriding of boundary and message ID creation
* Improve Brazilian Portuguese, Spanish, Swedish, Romanian, and German translations
* PHP 7.1 support for Travis-CI
* Fix some language codes
* Add security notices
* Improve DKIM compatibility in older PHP versions
* Improve trapping and capture of SMTP connection errors
* Improve passthrough of error levels for debug output
* PHPDoc cleanup

## Version 5.2.16 (June 6th 2016)
* Added DKIM example
* Fixed empty additional_parameters problem
Expand Down
113 changes: 86 additions & 27 deletions application/third_party/phpmailer/class.phpmailer.php
Expand Up @@ -31,7 +31,7 @@ class PHPMailer
* The PHPMailer Version number.
* @var string
*/
public $Version = '5.2.16';
public $Version = '5.2.19';

/**
* Email priority.
Expand Down Expand Up @@ -201,6 +201,9 @@ class PHPMailer
/**
* An ID to be used in the Message-ID header.
* If empty, a unique id will be generated.
* You can set your own, but it must be in the format "<id@domain>",
* as defined in RFC5322 section 3.6.4 or it will be ignored.
* @see https://tools.ietf.org/html/rfc5322#section-3.6.4
* @var string
*/
public $MessageID = '';
Expand Down Expand Up @@ -420,6 +423,13 @@ class PHPMailer
*/
public $DKIM_private = '';

/**
* DKIM private key string.
* If set, takes precedence over `$DKIM_private`.
* @var string
*/
public $DKIM_private_string = '';

/**
* Callback Action function name.
*
Expand Down Expand Up @@ -681,16 +691,16 @@ private function mailPassthru($to, $subject, $body, $header, $params)
} else {
$subject = $this->encodeHeader($this->secureHeader($subject));
}
//Can't use additional_parameters in safe_mode

//Can't use additional_parameters in safe_mode, calling mail() with null params breaks
//@link http://php.net/manual/en/function.mail.php
if (ini_get('safe_mode') or !$this->UseSendmailOptions) {
if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) {
$result = @mail($to, $subject, $body, $header);
} else {
$result = @mail($to, $subject, $body, $header, $params);
}
return $result;
}

/**
* Output debugging info via user-defined method.
* Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
Expand Down Expand Up @@ -1284,9 +1294,11 @@ public function preSend()

// Sign with DKIM if enabled
if (!empty($this->DKIM_domain)
&& !empty($this->DKIM_private)
&& !empty($this->DKIM_selector)
&& file_exists($this->DKIM_private)) {
&& (!empty($this->DKIM_private_string)
|| (!empty($this->DKIM_private) && file_exists($this->DKIM_private))
)
) {
$header_dkim = $this->DKIM_Add(
$this->MIMEHeader . $this->mailHeader,
$this->encodeHeader($this->secureHeader($this->Subject)),
Expand Down Expand Up @@ -1352,7 +1364,7 @@ public function postSend()
*/
protected function sendmailSend($header, $body)
{
if ($this->Sender != '') {
if (!empty($this->Sender)) {
if ($this->Mailer == 'qmail') {
$sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
} else {
Expand Down Expand Up @@ -1429,10 +1441,10 @@ protected function mailSend($header, $body)

$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 (!empty($this->Sender) and $this->validateAddress($this->Sender)) {
$params = sprintf('-f%s', escapeshellarg($this->Sender));
}
if ($this->Sender != '' and !ini_get('safe_mode')) {
if (!empty($this->Sender) and !ini_get('safe_mode') and $this->validateAddress($this->Sender)) {
$old_from = ini_get('sendmail_from');
ini_set('sendmail_from', $this->Sender);
}
Expand Down Expand Up @@ -1486,10 +1498,10 @@ protected function smtpSend($header, $body)
if (!$this->smtpConnect($this->SMTPOptions)) {
throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
}
if ('' == $this->Sender) {
$smtp_from = $this->From;
} else {
if (!empty($this->Sender) and $this->validateAddress($this->Sender)) {
$smtp_from = $this->Sender;
} else {
$smtp_from = $this->From;
}
if (!$this->smtp->mail($smtp_from)) {
$this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
Expand Down Expand Up @@ -1681,6 +1693,19 @@ public function smtpClose()
*/
public function setLanguage($langcode = 'en', $lang_path = '')
{
// Backwards compatibility for renamed language codes
$renamed_langcodes = array(
'br' => 'pt_br',
'cz' => 'cs',
'dk' => 'da',
'no' => 'nb',
'se' => 'sv',
);

if (isset($renamed_langcodes[$langcode])) {
$langcode = $renamed_langcodes[$langcode];
}

// Define full set of translatable strings in English
$PHPMAILER_LANG = array(
'authenticate' => 'SMTP Error: Could not authenticate.',
Expand All @@ -1707,6 +1732,10 @@ public function setLanguage($langcode = 'en', $lang_path = '')
// Calculate an absolute path so it can work if CWD is not here
$lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR;
}
//Validate $langcode
if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) {
$langcode = 'en';
}
$foundlang = true;
$lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
// There is no English translation file
Expand Down Expand Up @@ -2000,6 +2029,8 @@ public function createHeader()
$result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
}

// Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4
// https://tools.ietf.org/html/rfc5322#section-3.6.4
if ('' != $this->MessageID and preg_match('/^<.*@.*>$/', $this->MessageID)) {
$this->lastMessageID = $this->MessageID;
} else {
Expand Down Expand Up @@ -2105,6 +2136,14 @@ public function getSentMIMEMessage()
return rtrim($this->MIMEHeader . $this->mailHeader, "\n\r") . self::CRLF . self::CRLF . $this->MIMEBody;
}

/**
* Create unique ID
* @return string
*/
protected function generateId() {
return md5(uniqid(time()));
}

/**
* Assemble the message body.
* Returns an empty string on failure.
Expand All @@ -2116,7 +2155,7 @@ public function createBody()
{
$body = '';
//Create unique IDs and preset boundaries
$this->uniqueid = md5(uniqid(time()));
$this->uniqueid = $this->generateId();
$this->boundary[1] = 'b1_' . $this->uniqueid;
$this->boundary[2] = 'b2_' . $this->uniqueid;
$this->boundary[3] = 'b3_' . $this->uniqueid;
Expand Down Expand Up @@ -3296,16 +3335,18 @@ public function getCustomHeaders()
}

/**
* Create a message from an HTML string.
* Automatically makes modifications for inline images and backgrounds
* and creates a plain-text version by converting the HTML.
* Overwrites any existing values in $this->Body and $this->AltBody
* Create a message body from an HTML string.
* Automatically inlines images and creates a plain-text version by converting the HTML,
* overwriting any existing values in Body and AltBody.
* $basedir is used when handling relative image paths, e.g. <img src="images/a.png">
* will look for an image file in $basedir/images/a.png and convert it to inline.
* If you don't want to apply these transformations to your HTML, just set Body and AltBody yourself.
* @access public
* @param string $message HTML message string
* @param string $basedir baseline directory for path
* @param string $basedir base directory for relative paths to images
* @param boolean|callable $advanced Whether to use the internal HTML to text converter
* or your own custom converter @see PHPMailer::html2text()
* @return string $message
* @return string $message The transformed message Body
*/
public function msgHTML($message, $basedir = '', $advanced = false)
{
Expand Down Expand Up @@ -3375,7 +3416,7 @@ public function msgHTML($message, $basedir = '', $advanced = false)
* Convert an HTML string into plain text.
* This is used by msgHTML().
* Note - older versions of this function used a bundled advanced converter
* which was been removed for license reasons in #232
* which was been removed for license reasons in #232.
* Example usage:
* <code>
* // Use default conversion
Expand Down Expand Up @@ -3675,7 +3716,7 @@ public function DKIM_QP($txt)
* @access public
* @param string $signHeader
* @throws phpmailerException
* @return string
* @return string The DKIM signature value
*/
public function DKIM_Sign($signHeader)
{
Expand All @@ -3685,15 +3726,33 @@ public function DKIM_Sign($signHeader)
}
return '';
}
$privKeyStr = file_get_contents($this->DKIM_private);
if ($this->DKIM_passphrase != '') {
$privKeyStr = !empty($this->DKIM_private_string) ? $this->DKIM_private_string : file_get_contents($this->DKIM_private);
if ('' != $this->DKIM_passphrase) {
$privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
} else {
$privKey = openssl_pkey_get_private($privKeyStr);
}
if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) { //sha1WithRSAEncryption
openssl_pkey_free($privKey);
return base64_encode($signature);
//Workaround for missing digest algorithms in old PHP & OpenSSL versions
//@link http://stackoverflow.com/a/11117338/333340
if (version_compare(PHP_VERSION, '5.3.0') >= 0 and
in_array('sha256WithRSAEncryption', openssl_get_md_methods(true))) {
if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) {
openssl_pkey_free($privKey);
return base64_encode($signature);
}
} else {
$pinfo = openssl_pkey_get_details($privKey);
$hash = hash('sha256', $signHeader);
//'Magic' constant for SHA256 from RFC3447
//@link https://tools.ietf.org/html/rfc3447#page-43
$t = '3031300d060960864801650304020105000420' . $hash;
$pslen = $pinfo['bits'] / 8 - (strlen($t) / 2 + 3);
$eb = pack('H*', '0001' . str_repeat('FF', $pslen) . '00' . $t);

if (openssl_private_encrypt($eb, $signature, $privKey, OPENSSL_NO_PADDING)) {
openssl_pkey_free($privKey);
return base64_encode($signature);
}
}
openssl_pkey_free($privKey);
return '';
Expand Down
1 change: 1 addition & 0 deletions application/third_party/phpmailer/class.phpmaileroauth.php
Expand Up @@ -80,6 +80,7 @@ public function getOAUTHInstance()
* @uses SMTP
* @access public
* @return bool
* @throws phpmailerException
*/
public function smtpConnect($options = array())
{
Expand Down
2 changes: 1 addition & 1 deletion application/third_party/phpmailer/class.pop3.php
Expand Up @@ -34,7 +34,7 @@ class POP3
* @var string
* @access public
*/
public $Version = '5.2.16';
public $Version = '5.2.19';

/**
* Default POP3 port number.
Expand Down

0 comments on commit 450397e

Please sign in to comment.