VYPR
Critical severityOSV Advisory· Published Apr 17, 2019· Updated Aug 4, 2024

CVE-2019-10641

CVE-2019-10641

Description

Contao before 3.5.39 and 4.x before 4.7.3 has a Weak Password Recovery Mechanism for a Forgotten Password.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
contao/contaoPackagist
>= 4.0.0, < 4.4.374.4.37
contao/contaoPackagist
>= 4.5.0, < 4.7.34.7.3
contao/core-bundlePackagist
>= 4.0.0, < 4.4.374.4.37
contao/core-bundlePackagist
>= 4.5.0, < 4.7.34.7.3
contao/corePackagist
>= 3.0.0, < 3.5.393.5.39

Affected products

1

Patches

3
119a1b5bd9e6

Invalidate the user sessions if a password changes (see CVE-2019-10641)

https://github.com/contao/coreLeo FeyerApr 9, 2019via ghsa
5 files changed · +43 0
  • system/docs/CHANGELOG.md+7 0 modified
    @@ -1,6 +1,13 @@
     Contao Open Source CMS changelog
     ================================
     
    +Version 3.5.39 (2019-04-XX)
    +---------------------------
    +
    +### Fixed
    +Invalidate the user sessions if a password changes (see CVE-2019-10641).
    +
    +
     Version 3.5.38 (2018-12-21)
     ---------------------------
     
    
  • system/modules/core/dca/tl_member.php+4 0 modified
    @@ -608,6 +608,10 @@ public function setNewPassword($strPassword, $user)
     			}
     		}
     
    +		// Invalidate the user sessions if the password changes
    +		$this->Database->prepare("DELETE FROM tl_session WHERE name='FE_USER_AUTH' AND pid=? AND sessionID!=?")
    +					   ->execute($user->id, session_id());
    +
     		return $strPassword;
     	}
     
    
  • system/modules/core/dca/tl_user.php+24 0 modified
    @@ -242,6 +242,10 @@
     			'exclude'                 => true,
     			'inputType'               => 'password',
     			'eval'                    => array('mandatory'=>true, 'preserveTags'=>true, 'minlength'=>Config::get('minPasswordLength')),
    +			'save_callback' => array
    +			(
    +				array('tl_user', 'invalidateSessions')
    +			),
     			'sql'                     => "varchar(128) NOT NULL default ''"
     		),
     		'pwChange' => array
    @@ -732,6 +736,26 @@ public function checkAdminStatus($varValue, DataContainer $dc)
     	}
     
     
    +	/**
    +	 * Invalidate the user sessions if the password changes
    +	 *
    +	 * The password widget only triggers the save_callback if the password has actually
    +	 * changed, therefore we do not need to check the active record here.
    +	 *
    +	 * @param mixed         $varValue
    +	 * @param DataContainer $dc
    +	 *
    +	 * @return mixed
    +	 */
    +	public function invalidateSessions($varValue, DataContainer $dc)
    +	{
    +		$this->Database->prepare("DELETE FROM tl_session WHERE name='BE_USER_AUTH' AND pid=? AND sessionID!=?")
    +					   ->execute($dc->id, session_id());
    +
    +		return $varValue;
    +	}
    +
    +
     	/**
     	 * Prevent administrators from disabling their own account
     	 *
    
  • system/modules/core/modules/ModuleChangePassword.php+4 0 modified
    @@ -186,6 +186,10 @@ protected function compile()
     				}
     			}
     
    +			// Invalidate the user sessions if the password changes
    +			$this->Database->prepare("DELETE FROM tl_session WHERE name='FE_USER_AUTH' AND pid=? AND sessionID!=?")
    +						   ->execute($objMember->id, session_id());
    +
     			// Check whether there is a jumpTo page
     			if (($objJumpTo = $this->objModel->getRelated('jumpTo')) !== null)
     			{
    
  • system/modules/core/modules/ModulePassword.php+4 0 modified
    @@ -254,6 +254,10 @@ protected function setNewPassword()
     					}
     				}
     
    +				// Invalidate the user sessions if the password changes
    +				$this->Database->prepare("DELETE FROM tl_session WHERE name='FE_USER_AUTH' AND pid=? AND sessionID!=?")
    +							   ->execute($objMember->id, session_id());
    +
     				// Redirect to the jumpTo page
     				if (($objTarget = $this->objModel->getRelated('reg_jumpTo')) !== null)
     				{
    
b92e27bc7c9e

Invalidate the user sessions if a password changes (see CVE-2019-10641)

https://github.com/contao/contaoLeo FeyerApr 9, 2019via ghsa
4 files changed · +59 10
  • CHANGELOG.md+1 0 modified
    @@ -2,6 +2,7 @@
     
     ## DEV
     
    + * Invalidate the user sessions if a password changes (see CVE-2019-10641).
      * Correctly check if a file or folder is excluded from synchronization (see 410).
     
     ## 4.7.2 (2019-03-25)
    
  • core-bundle/src/Resources/contao/dca/tl_user.php+16 1 modified
    @@ -24,7 +24,8 @@
     		),
     		'onsubmit_callback' => array
     		(
    -			array('tl_user', 'storeDateAdded')
    +			array('tl_user', 'storeDateAdded'),
    +			array('tl_user', 'updateCurrentUser')
     		),
     		'sql' => array
     		(
    @@ -871,6 +872,20 @@ public function storeDateAdded(Contao\DataContainer $dc)
     					   ->execute($time, $dc->id);
     	}
     
    +	/**
    +	 * Update the current user if something changes, otherwise they would be
    +	 * logged out automatically
    +	 *
    +	 * @param Contao\DataContainer $dc
    +	 */
    +	public function updateCurrentUser(Contao\DataContainer $dc)
    +	{
    +		if ($this->User->id == $dc->id)
    +		{
    +			$this->User->findBy('id', $this->User->id);
    +		}
    +	}
    +
     	/**
     	 * Return the "toggle visibility" button
     	 *
    
  • core-bundle/src/Resources/contao/library/Contao/User.php+39 9 modified
    @@ -425,7 +425,7 @@ public function isMemberOf($id)
     			return false;
     		}
     
    -		$groups = StringUtil::deserialize($this->arrData['groups']);
    +		$groups = StringUtil::deserialize($this->groups);
     
     		// No groups assigned
     		if (empty($groups) || !\is_array($groups))
    @@ -519,15 +519,15 @@ public static function loadUserByUsername($username)
     	 */
     	public function getUsername()
     	{
    -		return $this->arrData['username'];
    +		return $this->username;
     	}
     
     	/**
     	 * {@inheritdoc}
     	 */
     	public function setUsername($username)
     	{
    -		$this->arrData['username'] = $username;
    +		$this->username = $username;
     
     		return $this;
     	}
    @@ -537,15 +537,15 @@ public function setUsername($username)
     	 */
     	public function getPassword()
     	{
    -		return $this->arrData['password'];
    +		return $this->password;
     	}
     
     	/**
     	 * {@inheritdoc}
     	 */
     	public function setPassword($password)
     	{
    -		$this->arrData['password'] = $password;
    +		$this->password = $password;
     
     		return $this;
     	}
    @@ -573,15 +573,33 @@ public function setSalt($salt)
     	 */
     	public function serialize()
     	{
    -		return serialize(array($this->id, $this->username, $this->disable, $this->admin, $this->groups));
    +		$data = array
    +		(
    +			'id' => $this->id,
    +			'username' => $this->username,
    +			'password' => $this->password,
    +			'admin' => $this->admin,
    +			'disable' => $this->disable,
    +			'start' => $this->start,
    +			'stop' => $this->stop
    +		);
    +
    +		return serialize($data);
     	}
     
     	/**
     	 * {@inheritdoc}
     	 */
     	public function unserialize($serialized)
     	{
    -		list($this->id, $this->username, $this->disable, $this->admin, $this->groups) = unserialize($serialized, array('allowed_classes'=>false));
    +		$data = unserialize($serialized, array('allowed_classes'=>false));
    +
    +		if (array_keys($data) != array('id', 'username', 'password', 'admin', 'disable', 'start', 'stop'))
    +		{
    +			return;
    +		}
    +
    +		list($this->id, $this->username, $this->password, $this->admin, $this->disable, $this->start, $this->stop) = array_values($data);
     	}
     
     	/**
    @@ -604,12 +622,12 @@ public function isEqualTo(UserInterface $user)
     			return false;
     		}
     
    -		if ((bool) $this->admin !== (bool) $user->admin)
    +		if ($this->password !== $user->password)
     		{
     			return false;
     		}
     
    -		if ($this->groups !== $user->groups)
    +		if ((bool) $this->admin !== (bool) $user->admin)
     		{
     			return false;
     		}
    @@ -619,6 +637,18 @@ public function isEqualTo(UserInterface $user)
     			return false;
     		}
     
    +		$time = Date::floorToMinute();
    +
    +		if ($this->start !== '' && $this->start > $time)
    +		{
    +			return false;
    +		}
    +
    +		if ($this->stop !== '' && $this->stop <= ($time + 60))
    +		{
    +			return false;
    +		}
    +
     		return true;
     	}
     
    
  • core-bundle/src/Resources/contao/modules/ModuleChangePassword.php+3 0 modified
    @@ -185,6 +185,9 @@ protected function compile()
     				}
     			}
     
    +			// Update the current user so they are not logged out automatically
    +			$this->User->findBy('id', $objMember->id);
    +
     			// Check whether there is a jumpTo page
     			if (($objJumpTo = $this->objModel->getRelated('jumpTo')) instanceof PageModel)
     			{
    
74c7dfafa0df

Invalidate the user sessions if a password changes (see CVE-2019-10641)

https://github.com/contao/contaoLeo FeyerApr 9, 2019via ghsa
5 files changed · +39 0
  • CHANGELOG.md+4 0 modified
    @@ -1,5 +1,9 @@
     # Change log
     
    +## DEV
    +
    + * Invalidate the user sessions if a password changes (see CVE-2019-10641).
    +
     ## 4.4.36 (2019-03-25)
     
      * Make custom layout section titles and IDs mandatory (see #341).
    
  • core-bundle/src/Resources/contao/dca/tl_member.php+4 0 modified
    @@ -607,6 +607,10 @@ public function setNewPassword($strPassword, $user)
     			}
     		}
     
    +		// Invalidate the user sessions if the password changes
    +		$this->Database->prepare("DELETE FROM tl_session WHERE name='FE_USER_AUTH' AND pid=? AND sessionID!=?")
    +					   ->execute($user->id, session_id());
    +
     		return $strPassword;
     	}
     
    
  • core-bundle/src/Resources/contao/dca/tl_user.php+23 0 modified
    @@ -254,6 +254,10 @@
     			'exclude'                 => true,
     			'inputType'               => 'password',
     			'eval'                    => array('mandatory'=>true, 'preserveTags'=>true, 'minlength'=>Config::get('minPasswordLength')),
    +			'save_callback' => array
    +			(
    +				array('tl_user', 'invalidateSessions')
    +			),
     			'sql'                     => "varchar(255) NOT NULL default ''"
     		),
     		'pwChange' => array
    @@ -742,6 +746,25 @@ public function getModules()
     		return $arrModules;
     	}
     
    +	/**
    +	 * Invalidate the user sessions if the password changes
    +	 *
    +	 * The password widget only triggers the save_callback if the password has actually
    +	 * changed, therefore we do not need to check the active record here.
    +	 *
    +	 * @param mixed         $varValue
    +	 * @param DataContainer $dc
    +	 *
    +	 * @return mixed
    +	 */
    +	public function invalidateSessions($varValue, DataContainer $dc)
    +	{
    +		$this->Database->prepare("DELETE FROM tl_session WHERE name='BE_USER_AUTH' AND pid=? AND sessionID!=?")
    +					   ->execute($dc->id, session_id());
    +
    +		return $varValue;
    +	}
    +
     	/**
     	 * Prevent administrators from downgrading their own account
     	 *
    
  • core-bundle/src/Resources/contao/modules/ModuleChangePassword.php+4 0 modified
    @@ -187,6 +187,10 @@ protected function compile()
     				}
     			}
     
    +			// Invalidate the user sessions if the password changes
    +			$this->Database->prepare("DELETE FROM tl_session WHERE name='FE_USER_AUTH' AND pid=? AND sessionID!=?")
    +						   ->execute($objMember->id, session_id());
    +
     			// Check whether there is a jumpTo page
     			if (($objJumpTo = $this->objModel->getRelated('jumpTo')) instanceof PageModel)
     			{
    
  • core-bundle/src/Resources/contao/modules/ModulePassword.php+4 0 modified
    @@ -254,6 +254,10 @@ protected function setNewPassword()
     					}
     				}
     
    +				// Invalidate the user sessions if the password changes
    +				$this->Database->prepare("DELETE FROM tl_session WHERE name='FE_USER_AUTH' AND pid=? AND sessionID!=?")
    +							   ->execute($objMember->id, session_id());
    +
     				// Redirect to the jumpTo page
     				if (($objTarget = $this->objModel->getRelated('reg_jumpTo')) instanceof PageModel)
     				{
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

10

News mentions

0

No linked articles in our index yet.