记一次对某博客系统登录认证缺陷的代码审计
字数 2021 2025-08-30 06:50:12
博客系统登录认证缺陷代码审计报告
1. 项目概述
MyBlog是一个基于以下技术栈实现的Java博客系统:
- SpringBoot
- Mybatis
- Thymeleaf
系统特点:
- 适合个人开发者、小型团队或教育机构使用
- 提供美观的界面和齐全的功能
- 部署简单,代码完善
- 允许用户专注于内容创作,系统处理技术细节
2. 环境搭建步骤
- 下载源代码并使用IDEA加载
- 创建数据库并导入数据库表数据文件
- 启动项目并在浏览器中访问
- 后台登录地址可通过访问特定URL进入
3. 代码审计重点
本次审计聚焦于用户登录认证过程中的业务设计缺陷,主要审计以下部分:
- 登录认证Controller层逻辑
- 用户服务实现类
- SQL查询与Mapper定义
- Cookie生成与验证机制
4. 登录认证流程分析
4.1 Controller层分析
文件路径:blog-master/src/main/java/com/my/blog/website/controller/admin/AuthController.java
主要逻辑:
- 获取用户登录认证失败次数
- 获取用户名和密码进行身份认证
- 处理认证结果
4.2 服务层实现
文件路径:blog-master/src/main/java/com/my/blog/website/service/impl/UserServiceImpl.java
认证流程:
- 检查用户名和密码是否为空
- 创建Example查询实例
- 添加SQL查询断言(要求用户名为输入的用户名)
- 调用底层SQL查询
4.3 DAO层与SQL映射
countByExample的DAO层定义:
- 使用MyBatis的Example查询方式
- 动态生成SQL语句
SQL映射文件:UserVomapper.xml
关键特性:
- 使用动态SQL生成WHERE子句
- 使用
foreach标签遍历oredcriteria集合 - 使用
trim去除特定前缀、关键词和后缀 - 条件判断使用
${}进行拼接
4.4 SQL注入分析
虽然使用了${}进行条件拼接,但实际不存在SQL注入风险的原因:
- 条件部分(如"username")是预定义的,不是用户输入
- 用户输入部分(值)被正确处理
- 条件与值分离的实现方式确保了安全性
条件构建过程:
- 构建二维List数组:
List(List("username",value)) - "username"是预定义的,用户只能控制value部分
最终生成的SQL语句示例:
SELECT COUNT(*) FROM users WHERE username = ?
5. 登录认证缺陷
5.1 用户枚举漏洞
存在差异响应:
- 当用户不存在时,返回"不存在该用户"
- 当用户存在但密码错误时,返回不同错误信息
这使得攻击者可以通过响应差异枚举有效用户名。
5.2 认证失败处理
认证失败流程:
- 进入catch块
error_count递增- 根据失败次数设置失败回显内容
问题:error_count检测逻辑无法有效防御用户枚举风险。
5.3 Cookie安全问题
认证成功后的Cookie设置:
- 设置用户Session
- 如果勾选"remember_me",调用
TaleUtils.setCookie设置Cookie
setCookie实现细节:
- 使用
Tools.enAes加密用户uid - 使用硬编码的AES盐值:
0123456789abcdef - Cookie键名为
S_L_ID - 设置生命周期后返回
安全问题分析:
- 硬编码加密密钥:AES盐值固定且公开
- 可预测的Cookie生成:使用uid和固定算法生成
- 缺乏系统唯一性:所有使用该系统的实例默认使用相同密钥
攻击场景:
- 攻击者识别目标使用此博客系统
- 从开源代码获取加密算法和盐值
- 查询数据库获取admin的uid(通常为1)
- 本地生成有效的管理员Cookie
- 使用生成的Cookie直接访问后台
6. 漏洞验证步骤
- 本地构建测试类生成有效Cookie:
// 示例测试类代码
String encryptedUID = Tools.enAes("1", "0123456789abcdef");
- 构造Cookie内容:
S_L_ID=[生成的加密值]
- 使用该Cookie刷新页面,可直接进入后台并正常操作
7. 修复建议
-
用户枚举问题:
- 统一认证失败的响应消息
- 实现延迟响应机制
-
Cookie安全问题:
- 使用系统安装时生成的随机密钥
- 实现密钥轮换机制
- 增加Cookie绑定IP或设备指纹
- 使用更安全的令牌生成方案(如JWT)
-
加密相关:
- 避免硬编码加密密钥
- 使用环境变量或配置文件存储密钥
- 考虑使用更强的加密算法
8. 总结
本案例揭示了以下安全问题和知识点:
- 认证逻辑缺陷:差异响应导致的用户枚举风险
- 加密实现问题:硬编码密钥导致的可预测令牌
- 动态SQL安全:正确理解MyBatis Example查询的安全性
- 系统唯一性:开源系统部署时应修改默认安全参数
审计要点:
- 关注认证流程中的差异响应
- 检查加密实现是否使用可预测的参数
- 理解框架特性以避免误判(如动态SQL的安全性)
- 识别硬编码的安全敏感信息