VYPR
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.

PackageAffected versionsPatched versions
yeswiki/yeswikiPackagist
< 4.4.54.4.5

Affected products

1

Patches

2
e1285709f6f6

fix(user): make lostPassword use better hashed link

https://github.com/YesWiki/yeswikiFlorian SchmittOct 31, 2024via ghsa
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'));
    
b5a8f93b8772

Merge commit from fork

https://github.com/YesWiki/yeswikiFlorianOct 31, 2024via ghsa
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

News mentions

0

No linked articles in our index yet.