High severityNVD Advisory· Published Oct 31, 2024· Updated Oct 31, 2024
Use of a Broken or Risky Cryptographic Algorithm in YesWiki
CVE-2024-51478
Description
YesWiki is a wiki system written in PHP. Prior to 4.4.5, the use of a weak cryptographic algorithm and a hard-coded salt to hash the password reset key allows it to be recovered and used to reset the password of any account. This issue is fixed in 4.4.5.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
yeswiki/yeswikiPackagist | < 4.4.5 | 4.4.5 |
Affected products
1Patches
2e1285709f6f6fix(user): make lostPassword use better hashed link
2 files changed · +9 −4
includes/services/UserManager.php+1 −0 modified@@ -34,6 +34,7 @@ class UserManager implements UserProviderInterface, PasswordUpgraderInterface protected $passwordHasherFactory; protected $securityController; protected $params; + protected $userlink; private $getOneByNameCacheResults;
tools/login/actions/LostPasswordAction.php+8 −4 modified@@ -10,20 +10,21 @@ use YesWiki\Core\Service\UserManager; use YesWiki\Core\YesWikiAction; use YesWiki\Security\Controller\SecurityController; +use YesWiki\Core\Service\PasswordHasherFactory; if (!function_exists('send_mail')) { require_once('includes/email.inc.php'); } class LostPasswordAction extends YesWikiAction { - private const PW_SALT = 'FBcA'; public const KEY_VOCABULARY = 'http://outils-reseaux.org/_vocabulary/key'; protected $authController; protected $errorType; protected $typeOfRendering; protected $securityController; + protected $passwordHasherFactory; protected $tripleStore; protected $userManager; @@ -34,6 +35,7 @@ public function run() $this->securityController = $this->getService(SecurityController::class); $this->tripleStore = $this->getService(TripleStore::class); $this->userManager = $this->getService(UserManager::class); + $this->passwordHasherFactory = $this->getService(PasswordHasherFactory::class); // init properties $this->errorType = null; @@ -206,16 +208,18 @@ private function manageSubStep(int $subStep): ?User private function sendPasswordRecoveryEmail(User $user) { // Generate the password recovery key - $key = md5($user['name'] . '_' . $user['email'] . random_int(0, 10000) . date('Y-m-d H:i:s') . self::PW_SALT); + $passwordHasher = $this->passwordHasherFactory->getPasswordHasher($user); + $plainKey = $user['name'] . '_' . $user['email'] . random_int(0, 10000) . date('Y-m-d H:i:s'); + $hashedKey = $passwordHasher->hash($plainKey); // Erase the previous triples in the trible table $this->tripleStore->delete($user['name'], self::KEY_VOCABULARY, null, '', '') ; // Store the (name, vocabulary, key) triple in triples table - $res = $this->tripleStore->create($user['name'], self::KEY_VOCABULARY, $key, '', ''); + $res = $this->tripleStore->create($user['name'], self::KEY_VOCABULARY, $hashedKey, '', ''); // Generate the recovery email $passwordLink = $this->wiki->Href('', '', [ 'a' => 'recover', - 'email' => $key, + 'email' => $hashedKey, 'u' => base64_encode($user['name']) ], false); $pieces = parse_url($this->params->get('base_url'));
1 file changed · +94 −0
includes/services/UserManager.php+94 −0 modified@@ -23,6 +23,10 @@ use YesWiki\Security\Controller\SecurityController; use YesWiki\Wiki; +if (!function_exists('send_mail')) { + require_once 'includes/email.inc.php'; +} + class UserManager implements UserProviderInterface, PasswordUpgraderInterface { protected $wiki; @@ -33,6 +37,7 @@ class UserManager implements UserProviderInterface, PasswordUpgraderInterface private $getOneByNameCacheResults; + public const KEY_VOCABULARY = 'http://outils-reseaux.org/_vocabulary/key'; public function __construct( Wiki $wiki, @@ -47,6 +52,7 @@ public function __construct( $this->securityController = $securityController; $this->params = $params; $this->getOneByNameCacheResults = []; + $this->userlink = ''; } private function arrayToUser(?array $userAsArray = null, bool $fillEmpty = false): ?User @@ -176,6 +182,94 @@ public function create($wikiNameOrUser, string $email = "", string $plainPasswor ); } + /* + * Password recovery process (AKA reset password) + * 1. A key is generated using name, email alongside with other stuff. + * 2. The triple (user's name, specific key "vocabulary",key) is stored in triples table. + * 3. In order to update h·er·is password, the user must provided that key. + * 4. The new password is accepted only if the key matches with the value in triples table. + * 5. The corresponding row is removed from triples table. + */ + + protected function generateUserLink($user) + { + // Generate the password recovery key + $passwordHasher = $this->passwordHasherFactory->getPasswordHasher($user); + $plainKey = $user['name'] . '_' . $user['email'] . random_int(0, 10000) . date('Y-m-d H:i:s'); + $hashedKey = $passwordHasher->hash($plainKey); + $tripleStore = $this->wiki->services->get(TripleStore::class); + // Erase the previous triples in the trible table + $tripleStore->delete($user['name'], self::KEY_VOCABULARY, null, '', ''); + // Store the (name, vocabulary, key) triple in triples table + $tripleStore->create($user['name'], self::KEY_VOCABULARY, $hashedKey, '', ''); + + // Generate the recovery email + $this->userlink = $this->wiki->Href('', 'MotDePassePerdu', [ + 'a' => 'recover', + 'email' => $hashedKey, + 'u' => base64_encode($user['name']), + ], false); + } + + /** + * Part of the Password recovery process: Handles the password recovery email process. + * + * Generates the password recovery key + * Stores the (name, vocabulary, key) triple in triples table + * Generates the recovery email + * Sends it + * + * @return bool True if OK or false if any problems + */ + public function sendPasswordRecoveryEmail(User $user, string $title): bool + { + $this->generateUserLink($user); + $pieces = parse_url($this->params->get('base_url')); + $domain = isset($pieces['host']) ? $pieces['host'] : ''; + + $message = _t('LOGIN_DEAR') . ' ' . $user['name'] . ",\n"; + $message .= _t('LOGIN_CLICK_FOLLOWING_LINK') . ' :' . "\n"; + $message .= '-----------------------' . "\n"; + $message .= $this->userlink . "\n"; + $message .= '-----------------------' . "\n"; + $message .= _t('LOGIN_THE_TEAM') . ' ' . $domain . "\n"; + + $subject = $title . ' ' . $domain; + // Send the email + return send_mail($this->params->get('BAZ_ADRESSE_MAIL_ADMIN'), $this->params->get('BAZ_ADRESSE_MAIL_ADMIN'), $user['email'], $subject, $message); + } + + /** + * Assessor for userlink field. + */ + public function getUserLink(): string + { + return $this->userlink; + } + + /** + * Assessor for userlink field. + */ + public function getLastUserLink(User $user): string + { + $passwordHasher = $this->passwordHasherFactory->getPasswordHasher($user); + $plainKey = $user['name'] . '_' . $user['email'] . random_int(0, 10000) . date('Y-m-d H:i:s'); + $hashedKey = $passwordHasher->hash($plainKey); + $tripleStore = $this->wiki->services->get(TripleStore::class); + $key = $tripleStore->getOne($user['name'], self::KEY_VOCABULARY, '', ''); + if ($key != null) { + $this->userlink = $this->wiki->Href('', 'MotDePassePerdu', [ + 'a' => 'recover', + 'email' => $key, + 'u' => base64_encode($user['name']), + ], false); + } else { + $this->generateUserLink($user); + } + + return $this->userlink; + } + /** * update user params * for e-mail check is existing e-mail
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-4fvx-h823-38v3ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-51478ghsaADVISORY
- github.com/YesWiki/yeswiki/commit/b5a8f93b87720d5d5f033a4b3a131ce0fb621dbcghsax_refsource_MISCWEB
- github.com/YesWiki/yeswiki/commit/e1285709f6f6a2277bd0075acf369f33cefd78f7ghsax_refsource_MISCWEB
- github.com/YesWiki/yeswiki/security/advisories/GHSA-4fvx-h823-38v3ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.