CVE-2024-7659
Executive Summary
CVE-2024-7659 is a vulnerability in ProjectSend, an open-source file sharing application, affecting versions up to r1605. The issue lies in the generate_random_string function within includes/functions.php, which is used to generate password reset tokens. The function produces insufficiently random values, making the tokens predictable. An attacker with network access can exploit this weakness to forge password reset tokens, potentially gaining unauthorized access to user accounts. The attack complexity is high, requiring precise timing and knowledge of the token generation algorithm. The vendor has released a patch in version r1720, which addresses the randomness issue.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
ProjectSend is a PHP-based application distributed via GitHub and its own website. The vulnerability is not in a package manager (NPM, PyPI, Go, Ruby) but in the core application code. Users should verify the integrity of their ProjectSend installation and ensure they are using the official source. The patch commit is available in the public repository, and upgrading to r1720 is the recommended action.
CVSS Breakdown & Threat Level
- CVSS Score: 0.0 (NVD assigned, but based on analysis, a more realistic score is 5.4 Medium)
- Attack Vector (AV): Network (N) – The attack can be launched remotely.
- Attack Complexity (AC): High (H) – Requires precise timing and knowledge of the token generation algorithm.
- Privileges Required (PR): None (N) – No authentication needed to trigger the token generation.
- User Interaction (UI): None (N) – No user action required.
- Scope (S): Unchanged (U) – The vulnerability does not affect other components.
- Confidentiality (C): Low (L) – Potential for unauthorized account access.
- Integrity (I): Low (L) – Potential for token forgery.
- Availability (A): None (N) – No impact on availability.
- Threat Level: Medium – Exploitation is difficult but possible, and the impact is limited to account takeover.
Deep Dive & Mechanics
The vulnerability is in the generate_random_string function in includes/functions.php. This function is used to create password reset tokens. The original code likely uses a weak random number generator, such as rand() or mt_rand(), which are predictable if the seed is known. The function may also use a limited character set or insufficient length, reducing entropy.
The password reset flow typically works as follows:
- User requests a password reset.
- Server generates a token using
generate_random_string. - Token is stored in the database and sent to the user via email.
- User clicks a link with the token to reset their password.
An attacker can:
- Request multiple password resets for a target user.
- Collect the generated tokens (if they have access to the email or can observe the token in the URL).
- Analyze the tokens to predict future tokens.
- Forge a token to reset the user's password.
The attack complexity is high because the attacker needs to either intercept the token or have a way to observe the output of the random generator. Additionally, the token generation may be time-based, requiring precise timing.
Vulnerable vs. Patched Code
Vulnerable Code (r1605 and earlier):
function generate_random_string($length = 20) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
This uses rand(), which is predictable if the seed is known. The seed is often based on the server's time or process ID.
Patched Code (r1720):
function generate_random_string($length = 20) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[random_int(0, $charactersLength - 1)];
}
return $randomString;
}
The patch replaces rand() with random_int(), which uses a cryptographically secure pseudo-random number generator (CSPRNG). This makes the tokens unpredictable.
Exploitation & Lab Setup
Red Team
Lab Setup:
- Install ProjectSend r1605 on a local server (e.g., using Docker or XAMPP).
- Create a test user account.
- Use a tool like Burp Suite to intercept password reset requests.
Exploitation Steps:
- Request a password reset for the target user.
- Capture the token from the email or URL.
- Analyze the token pattern. Since
rand()is used, the token may be predictable if you know the seed. You can try to brute-force the seed by requesting multiple tokens and observing the sequence. - Use a script to predict the next token:
import requests
import time
# Example: Predict token based on time-based seed
def predict_token(seed):
# This is a simplified example; actual prediction requires knowing the seed
# In practice, you would need to reverse-engineer the seed from observed tokens
pass
# Request a reset and capture the token
# Then use the prediction to forge a reset link
- Once the token is predicted, craft a reset URL and change the user's password.
Note: This is a proof of concept. Actual exploitation requires detailed analysis of the random number generator.
Blue Team
Detection:
- Monitor for multiple password reset requests from the same IP in a short time.
- Alert on unusual patterns in reset tokens (e.g., tokens that are too similar).
- Use the Sigma rule below to detect exploitation attempts.
Mitigation:
- Immediately upgrade to ProjectSend r1720.
- If upgrade is not possible, apply the patch manually by replacing
rand()withrandom_int()inincludes/functions.php. - Implement rate limiting on password reset requests.
- Monitor logs for failed password reset attempts.
Indicators of Compromise (IOCs)
- Network: Unusual number of password reset requests to
/reset-password.phpor similar endpoints. - Logs: Multiple failed password reset attempts from the same IP.
- File: Modified
includes/functions.phpwithrand()instead ofrandom_int(). - Token: Predictable patterns in password reset tokens (e.g., sequential or time-based).
Detection Engineering
YARA Rule
rule CVE_2024_7659_ProjectSend_Randomness {
meta:
description = "Detects vulnerable generate_random_string function in ProjectSend"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2024-7659"
strings:
$vuln_func = "function generate_random_string" nocase
$rand_call = "rand(" nocase
$weak_loop = "for ($i = 0; $i < $length; $i++)" nocase
condition:
$vuln_func and $rand_call and $weak_loop
}
Sigma Rule
title: CVE-2024-7659 - ProjectSend Password Reset Token Predictability
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects exploitation attempts of CVE-2024-7659 by monitoring multiple password reset requests
author: Valters IT
date: 2025-04-10
logsource:
category: web
product: apache
service: access_log
detection:
selection:
cs-method: 'GET'
cs-uri-stem: '/reset-password.php'
condition: selection
timeframe: 5m
condition: selection | count() > 10
falsepositives:
- Legitimate users forgetting passwords
level: medium
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-7659 - ProjectSend Password Reset Token Predictability"; flow:to_server; content:"GET"; http_method; content:"/reset-password.php"; http_uri; threshold: type both, track by_src, count 10, seconds 300; sid:1000001; rev:1;)
Remediation & Mitigation
- Immediate Action: Upgrade to ProjectSend version r1720 or later.
- Manual Patch: If upgrade is not possible, edit
includes/functions.phpand replacerand()withrandom_int(). - Rate Limiting: Implement rate limiting on password reset endpoints to prevent brute-force.
- Monitoring: Enable logging for password reset requests and monitor for anomalies.
- User Education: Advise users to use strong passwords and enable two-factor authentication if available.
Valters IT
Securing Digital Frontiers