29 changes: 12 additions & 17 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contao/switch.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
define('TL_SCRIPT', 'contao/switch.php');

// Initialize the system
define('TL_MODE', 'FE');
define('TL_MODE', 'BE');
require dirname(__DIR__) . '/system/initialize.php';

// Run the controller
Expand Down
2 changes: 1 addition & 1 deletion system/config/constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* Core version
*/
define('VERSION', '3.5');
define('BUILD', '31');
define('BUILD', '32');
define('LONG_TERM_SUPPORT', true);


Expand Down
13 changes: 13 additions & 0 deletions system/docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
Contao Open Source CMS changelog
================================

Version 3.5.32 (2018-01-18)
---------------------------

### Fixed
Fix an XSS vulnerability in the newsletter module (see CVE-2018-5478).

### Fixed
Do not remove old subscriptions not related to the channels (see #8824).

### Fixed
Backport the password algorithm changes from Contao 4 (see #8820).


Version 3.5.31 (2017-11-15)
---------------------------

Expand Down
2 changes: 1 addition & 1 deletion system/modules/core/classes/StyleSheets.php
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ public function compileDefinition($row, $blnWriteToFile=false, $vars=array(), $p
$own = preg_replace('/url\("(?!data:|\/)/', 'url("' . $strGlue, $own);
$own = preg_split('/[\n\r]+/', $own);
$own = implode(($blnWriteToFile ? '' : $lb), $own);
$return .= $lb . (!$blnWriteToFile ? specialchars($own) : $own);
$return .= $lb . ((!$blnWriteToFile && !$export) ? specialchars($own) : $own);
}

// Allow custom definitions
Expand Down
43 changes: 21 additions & 22 deletions system/modules/core/controllers/BackendInstall.php
Original file line number Diff line number Diff line change
Expand Up @@ -340,33 +340,32 @@ protected function loginUser()
$_SESSION['TL_INSTALL_AUTH'] = '';
$_SESSION['TL_INSTALL_EXPIRE'] = 0;

// The password has been generated with crypt()
if (\Encryption::test(\Config::get('installPassword')))
{
if (\Encryption::verify(\Input::postUnsafeRaw('password'), \Config::get('installPassword')))
{
$this->setAuthCookie();
\Config::persist('installCount', 0);
$blnNeedsRehash = true;

$this->reload();
}
// Handle old sha1() passwords with an optional salt
if (preg_match('/^[a-f0-9]{40}(:[a-f0-9]{23})?$/', \Config::get('installPassword')))
{
list($strPassword, $strSalt) = explode(':', \Config::get('installPassword'));
$blnAuthenticated = ($strPassword === sha1($strSalt . \Input::postUnsafeRaw('password')));
}
else
{
list($strPassword, $strSalt) = explode(':', \Config::get('installPassword'));
$blnAuthenticated = ($strSalt == '') ? ($strPassword === sha1(\Input::postUnsafeRaw('password'))) : ($strPassword === sha1($strSalt . \Input::postUnsafeRaw('password')));
$blnAuthenticated = password_verify(\Input::postUnsafeRaw('password'), \Config::get('installPassword'));
$blnNeedsRehash = password_needs_rehash(\Config::get('installPassword'), PASSWORD_DEFAULT);
}

if ($blnAuthenticated)
{
// Store a crypt() version of the password
$strPassword = \Encryption::hash(\Input::postUnsafeRaw('password'));
\Config::persist('installPassword', $strPassword);
// Re-hash the password if the algorithm has changed
if ($blnAuthenticated && $blnNeedsRehash)
{
\Config::persist('installPassword', password_hash(\Input::postUnsafeRaw('password'), PASSWORD_DEFAULT));
}

$this->setAuthCookie();
\Config::persist('installCount', 0);
if ($blnAuthenticated)
{
$this->setAuthCookie();
\Config::persist('installCount', 0);

$this->reload();
}
$this->reload();
}

// Increase the login count if we get here
Expand Down Expand Up @@ -398,7 +397,7 @@ protected function storeInstallToolPassword()
// Save the password
else
{
$strPassword = \Encryption::hash($strPassword);
$strPassword = password_hash($strPassword, PASSWORD_DEFAULT);
\Config::persist('installPassword', $strPassword);

$this->reload();
Expand Down Expand Up @@ -768,7 +767,7 @@ protected function createAdminUser()
elseif (\Input::post('name') != '' && \Input::post('email', true) != '' && \Input::post('username', true) != '')
{
$time = time();
$strPassword = \Encryption::hash(\Input::postUnsafeRaw('pass'));
$strPassword = password_hash(\Input::postUnsafeRaw('pass'), PASSWORD_DEFAULT);

$this->Database->prepare("INSERT INTO tl_user (tstamp, name, email, username, password, language, backendTheme, admin, showHelp, useRTE, useCE, thumbnails, dateAdded) VALUES ($time, ?, ?, ?, ?, ?, ?, 1, 1, 1, 1, 1, $time)")
->execute(\Input::post('name'), \Input::post('email', true), \Input::post('username', true), $strPassword, str_replace('-', '_', $GLOBALS['TL_LANGUAGE']), \Config::get('backendTheme'));
Expand Down
4 changes: 2 additions & 2 deletions system/modules/core/controllers/BackendPassword.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public function run()
else
{
// Make sure the password has been changed
if (\Encryption::verify($pw, $this->User->password))
if (password_verify($pw, $this->User->password))
{
\Message::addError($GLOBALS['TL_LANG']['MSC']['pw_change']);
}
Expand All @@ -99,7 +99,7 @@ public function run()

$objUser = \UserModel::findByPk($this->User->id);
$objUser->pwChange = '';
$objUser->password = \Encryption::hash($pw);
$objUser->password = password_hash($pw, PASSWORD_DEFAULT);
$objUser->save();

\Message::addConfirmation($GLOBALS['TL_LANG']['MSC']['pw_changed']);
Expand Down
2 changes: 1 addition & 1 deletion system/modules/core/forms/FormPassword.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ protected function validator($varInput)
{
$this->blnSubmitInput = true;

return \Encryption::hash($varInput);
return password_hash($varInput, PASSWORD_DEFAULT);
}

return '';
Expand Down
1 change: 1 addition & 0 deletions system/modules/core/languages/es/tl_settings.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@
</trans-unit>
<trans-unit id="tl_settings.maxImageWidth.1">
<source>If the width of an image or movie exceeds this value, it will be adjusted automatically. Set to 0 to disable the limit.</source>
<target>Si el ancho de una imagen o película excede este valor, se ajustará automáticamente. Establézcalo en 0 para desactivar el límite.</target>
</trans-unit>
<trans-unit id="tl_settings.jpgQuality.0">
<source>JPG thumbnail quality</source>
Expand Down
1 change: 1 addition & 0 deletions system/modules/core/languages/lv/countries.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,7 @@
</trans-unit>
<trans-unit id="CNT.vi">
<source>U.S. Virgin Islands</source>
<target>ASV Virdžīnas</target>
</trans-unit>
<trans-unit id="CNT.vn">
<source>Vietnam</source>
Expand Down
1 change: 1 addition & 0 deletions system/modules/core/languages/zh/tl_settings.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@
</trans-unit>
<trans-unit id="tl_settings.maxImageWidth.1">
<source>If the width of an image or movie exceeds this value, it will be adjusted automatically. Set to 0 to disable the limit.</source>
<target>如果一张图片或者视频的宽度超出所设定的数值,它将会自动调整。设置0禁用这个限制。</target>
</trans-unit>
<trans-unit id="tl_settings.jpgQuality.0">
<source>JPG thumbnail quality</source>
Expand Down
76 changes: 8 additions & 68 deletions system/modules/core/library/Contao/Encryption.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

namespace Contao;

@trigger_error('Using the Contao\Encryption class has been deprecated and will no longer work in Contao 5.0. Use the PHP password_* functions and a third-party library such as OpenSSL or phpseclib instead.', E_USER_DEPRECATED);


/**
* Encrypts and decrypts data
Expand All @@ -23,6 +25,9 @@
* $decrypted = Encryption::decrypt($encrypted);
*
* @author Leo Feyer <https://github.com/leofeyer>
*
* @deprecated Deprecated since Contao 3.5, to be removed in Contao 5.0.
* Use the PHP password_* functions and a third-party library such as OpenSSL or phpseclib instead.
*/
class Encryption
{
Expand All @@ -47,14 +52,9 @@ class Encryption
* @param string $strKey An optional encryption key
*
* @return string The encrypted value
*
* @deprecated Deprecated since Contao 3.5, to be removed in Contao 5.
* Use a third-party library such as OpenSSL or phpseclib instead.
*/
public static function encrypt($varValue, $strKey=null)
{
@trigger_error('Using Encryption::encrypt() has been deprecated and will no longer work in Contao 5.0. Use a third-party library such as OpenSSL or phpseclib instead.', E_USER_DEPRECATED);

// Recursively encrypt arrays
if (is_array($varValue))
{
Expand Down Expand Up @@ -98,14 +98,9 @@ public static function encrypt($varValue, $strKey=null)
* @param string $strKey An optional encryption key
*
* @return string The decrypted value
*
* @deprecated Deprecated since Contao 3.5, to be removed in Contao 5.
* Use a third-party library such as OpenSSL or phpseclib instead.
*/
public static function decrypt($varValue, $strKey=null)
{
@trigger_error('Using Encryption::decrypt() has been deprecated and will no longer work in Contao 5.0. Use a third-party library such as OpenSSL or phpseclib instead.', E_USER_DEPRECATED);

// Recursively decrypt arrays
if (is_array($varValue))
{
Expand Down Expand Up @@ -180,36 +175,10 @@ protected static function initialize()
* @param string $strPassword The unencrypted password
*
* @return string The encrypted password
*
* @throws \Exception If none of the algorithms is available
*/
public static function hash($strPassword)
{
$intCost = \Config::get('bcryptCost') ?: 10;

if ($intCost < 4 || $intCost > 31)
{
throw new \Exception("The bcrypt cost has to be between 4 and 31, $intCost given");
}

if (function_exists('password_hash'))
{
return password_hash($strPassword, PASSWORD_BCRYPT, array('cost'=>$intCost));
}
elseif (CRYPT_BLOWFISH == 1)
{
return crypt($strPassword, '$2y$' . sprintf('%02d', $intCost) . '$' . md5(uniqid(mt_rand(), true)) . '$');
}
elseif (CRYPT_SHA512 == 1)
{
return crypt($strPassword, '$6$' . md5(uniqid(mt_rand(), true)) . '$');
}
elseif (CRYPT_SHA256 == 1)
{
return crypt($strPassword, '$5$' . md5(uniqid(mt_rand(), true)) . '$');
}

throw new \Exception('None of the required crypt() algorithms is available');
return password_hash($strPassword, PASSWORD_DEFAULT);
}


Expand Down Expand Up @@ -255,37 +224,12 @@ public static function test($strHash)
*/
public static function verify($strPassword, $strHash)
{
if (function_exists('password_verify'))
{
return password_verify($strPassword, $strHash);
}

$getLength = function($str) {
return extension_loaded('mbstring') ? mb_strlen($str, '8bit') : strlen($str);
};

$newHash = crypt($strPassword, $strHash);

if (!is_string($newHash) || $getLength($newHash) != $getLength($strHash) || $getLength($newHash) <= 13)
{
return false;
}

$intStatus = 0;

for ($i=0; $i<$getLength($newHash); $i++)
{
$intStatus |= (ord($newHash[$i]) ^ ord($strHash[$i]));
}

return $intStatus === 0;
return password_verify($strPassword, $strHash);
}


/**
* Initialize the encryption module
*
* @deprecated Encryption is now a static class
*/
protected function __construct()
{
Expand All @@ -295,18 +239,14 @@ protected function __construct()

/**
* Prevent cloning of the object (Singleton)
*
* @deprecated Encryption is now a static class
*/
final public function __clone() {}


/**
* Return the object instance (Singleton)
*
* @return \Encryption
*
* @deprecated Encryption is now a static class
* @return Encryption
*/
public static function getInstance()
{
Expand Down
Loading