记对某CMS的一次代码审计
字数 894 2025-08-25 22:58:20
某CMS认证逻辑缺陷漏洞分析与复现
漏洞概述
该CMS在处理登录认证时存在设计缺陷,导致admin用户可以在不校验密码的情况下直接登录系统。漏洞源于SQL查询语句逻辑设计不当,使得密码验证条件被绕过。
漏洞分析
1. 认证流程分析
-
初始登录页面:
oa.php?c=Public&a=login- 加载
login.tpl模板文件 - 表单提交到
oa.php?c=Public&a=check_login
- 加载
-
认证处理流程:
- 验证码检查(如果启用)
- 账号密码非空检查
- 特殊处理:当用户名为
admin时直接设置ADMIN_AUTH_KEY会话变量 - 构造查询条件并调用
check_login方法
2. 关键漏洞代码
问题SQL语句(位于source/model/oa/model.login.php):
$sql = "SELECT * FROM ".DB_PREFIXOA."user WHERE emp_no='".$emp_no."' OR name='".$emp_no."' AND is_del='".$is_del."' AND password='".$password."'";
SQL逻辑问题:
- 由于AND优先级高于OR,实际执行逻辑为:
SELECT * FROM PREFIXOA_user WHERE (emp_no='admin') OR (name='admin' AND is_del='0' AND password='[md5值]') - 当用户名为
admin时,emp_no='admin'条件始终为真,导致整个WHERE条件为真 - 正确设计应为:
$sql = "SELECT * FROM ".DB_PREFIXOA."user WHERE ((emp_no='".$emp_no."') OR (name='".$emp_no."')) AND (is_del='".$is_del."') AND (password='".$password."')";
3. 认证绕过流程
- 提交
admin账号和任意密码 - 系统构造SQL查询
- 由于SQL逻辑问题,返回admin用户记录
- 系统认为认证成功,设置会话变量:
$_SESSION['USER_AUTH_KEY'] = $auth_info['id']; $_SESSION['emp_no'] = $auth_info['emp_no']; $_SESSION['user_name'] = $auth_info['name']; // 其他会话变量... - 重定向到
oa.php,完成登录
漏洞复现步骤
-
访问登录页面:
http://[target]/oa.php?c=Public&a=login -
在登录表单中输入:
- 用户名:
admin - 密码:任意值(如
123456)
- 用户名:
-
提交表单,观察是否成功登录系统后台
修复建议
-
修改SQL查询逻辑:
$sql = "SELECT * FROM ".DB_PREFIXOA."user WHERE (emp_no=? OR name=?) AND is_del=? AND password=?"; -
使用预处理语句:
- 采用参数化查询防止SQL注入
- 使用PDO或mysqli预处理
-
加强认证逻辑:
- 移除对admin账号的特殊处理
- 严格验证所有认证条件
-
日志记录:
- 记录失败的登录尝试
- 监控异常登录行为
总结
该漏洞展示了SQL查询逻辑设计不当可能导致的安全问题。开发人员应当:
- 仔细设计SQL查询逻辑,必要时使用括号明确优先级
- 避免在认证流程中加入特殊例外
- 采用安全的数据库查询方式
- 对关键业务流程进行充分的测试和安全审计
通过此案例,我们认识到即使是看似简单的SQL语句,如果逻辑设计不当,也可能导致严重的安全漏洞。