sdcms php ee v3.1 前台搜索 SQL 注入漏洞
漏洞类型: SQL 注入(时间盲注)
影响版本: SDCMS PHP EE 3.1
触发入口: index.php?m=home&c=other&a=search
权限要求: 前台匿名访问
测试环境: PHP 7.4.3、MySQL 5.7.26
验证状态: 本地复现成功,厂商已于 2026-11-08 发布新版本修复。
本文仅供网络安全研究和防御目的使用。请勿在未经授权的情况下将本文中的技术或代码用于攻击任何目标系统。由于本文发布时,厂商已发布修复补丁,任何未授权利用所导致的法律及连带责任由攻击者本人承担,与本作者无关。
1. 漏洞概述
SDCMS PHP EE 3.1 的前台搜索功能存在 SQL 注入。用户提交的 keyword 经过参数处理后,被直接拼接到 SQL 查询语句中。攻击者无需登录即可构造特殊输入,通过响应时间判断 SQL 查询结果。
本地测试已验证时间盲注,并读取到数据库名称、版本及管理员密码哈希。
2. 漏洞分析
漏洞位于 app/home/controller/other.php 的 search() 方法:
$where = "islock=1";
$where .= " and (";
$where .= " title like '%{$keyword}%' or intro like '%{$keyword}%' ";
$where .= ")";
$rs = $this->db->row(
"select id from sd_content $join where $where order by id desc limit 1"
);
$keyword 被直接放入 LIKE 条件中,随后作为 SQL 语句的一部分交给数据库执行。这里没有使用预处理语句,也没有通过参数绑定传递搜索内容。
参数处理过程
搜索参数通过 F() 获取,该函数会调用 filter_html()、enhtml() 等处理函数;其中 enhtml() 包含 URL 解码和 HTML 特殊字符转换。控制器在 POST 分支中还会再次调用 urldecode(),然后将关键词保存到 Session。
测试请求过程如下:
- POST 请求提交关键词,PHP 表单解析、
enhtml()和控制器中的urldecode()依次处理参数。 - 控制器将处理后的关键词写入 Session。
- 后续 GET 请求从 Session 取出关键词,再执行一次
urldecode()。 - 解码后的关键词进入搜索 SQL。
测试脚本将载荷 URL 编码三次,对应 POST 阶段的三次解码。GET 阶段还会对 Session 中的内容再解码一次。这个编码过程对应本文使用的 POST/Session/GET 请求方式;直接通过 GET 参数提交时,处理流程并不相同。
项目中的 htmlspecialchars() 处理用于 HTML 特殊字符转换,不能防止 SQL 注入。数据库类中虽然还有关键字替换和 filter_char() 等处理,但根据当前代码调用关系,filter_char() 没有用于这里的搜索查询。
3. 漏洞验证
前置条件
搜索语句包含 islock=1,本次时间盲注测试时,sd_content 表中需要存在符合条件的已发布内容。全新安装默认没有相关记录,需要管理员在手动添加一条内容记录。
时间盲注
测试脚本先通过 POST 保存载荷,再携带相同 Session Cookie 发起 GET 请求,并统计 GET 请求耗时。使用下面 payload 在前台进行搜索框进行搜索可以观察到站点加载了多秒后返回提示,成功执行了 sleep 函数。
注:以下 Payload 仅用于本地环境漏洞验证。该漏洞已由厂商在最新版本中修复。
在前台搜索框中提交该 Payload:
%2527%2520and%2520sleep%25282%2529%2520and%25201%2520like%2520%2527
或者通过 Burp Suite 发送以下请求(手动替换参数)
POST /?m=search HTTP/1.1
Host: <Your_Host>:8080
Content-Type: application/x-www-form-urlencoded
Content-Length: 153
Cookie: PHPSESSID=<Your_SESSION_ID>
Connection: close
c=other&a=search&token=<Your_TOKEN>&keyword=%252527%252520and%252520sleep%2525282%252529%252520and%2525201%252520like%252520%252527
4. 影响范围
- 未登录用户可以触发前台搜索查询。
- 可以利用响应时间判断 SQL 表达式结果。
- 本地测试读取到了数据库名称及版本信息和管理员密码哈希。
该漏洞的直接后果是导致敏感数据泄露。在特定条件下,危害可进一步升级:如果管理员使用弱口令,攻击者可能通过离线破解获取明文密码并登录后台,利用后台模板编辑功能修改并执行 PHP 代码,从而实现远程代码执行(RCE)。
5. 修复建议
- 建议将搜索查询改为预处理语句,通过参数绑定传入关键词:
- 检查并清理重复的
urldecode()调用,明确参数在哪一层解码。 - 不要用 HTML 转义或 SQL 关键字黑名单代替 SQL 参数绑定。
- 动态表名、字段名和排序方式应使用白名单限制。
- 排查项目中其他将用户输入拼接进 SQL 的位置。
6. 修复情况
厂商在收到反馈后,于 2026 年 11 月 8 日发布了新版本修复了该问题。本文公开时,新版本已可下载。