CVE-2026-34973 phpMyFAQ LIKE 通配符注入漏洞分析与复现
字数 1923
更新时间 2026-10-07 00:08:55

CVE-2026-34973 phpMyFAQ LIKE 通配符注入漏洞分析与复现

phpMyFAQ 是一款基于 PHP 的开源 FAQ(常见问题解答)系统。CVE-2026-34973 的特殊之处在于:代码已经按教科书做了 SQL 注入防御(对输入调用 mysqli::real_escape_string()),但防御范围没覆盖到 LIKE 子句的语义层——这恰好是很多开发者容易忽视的安全盲区。

一、漏洞机制

phpMyFAQ 的公开搜索功能在检索自定义页面时,将用户输入用 real_escape_string() 转义后直接拼入 LIKE 子句。问题在于职责边界:

  • real_escape_string() 的设计目标是转义 SQL 字符串界定符('、"、\),防止输入提前闭合字符串、破坏 SQL 语法结构。
  • 但 LIKE 子句的通配符 %(匹配任意字符序列)和 _(匹配单个字符)在 SQL 标准中属于“模式匹配元字符”,不属于字符串界定符,因此不会被转义。

当搜索词由这些通配符构成时,它们会按 LIKE 的语义被解释:“任意位置含若干字符”一类的全匹配条件,从而将搜索范围从“匹配指定关键词”放大为“匹配表中所有非空行”。任何能访问搜索页的人——无需登录——就能一次性拿到全部自定义页面内容,包括本应仅限内部查看的管理文档。

二、为什么防御会失效

多数开发者的心智模型是“用了参数化/转义就安全了”,但这个模型隐含一个假设:SQL 注入只发生在字符串边界。LIKE 通配符注入打破了这一假设——它不修改 SQL 结构,而是改变数据匹配的语义。因此即便不存在传统意义上的“拼接型 SQL 注入”,仍可能出现“语义越权”式的信息泄露。

它的隐蔽性也在这里:代码审计时看到 real_escape_string() 调用,很容易自然地把它标为“已安全”。只有同时意识到“这段代码用了 LIKE”与“LIKE 有自己的通配符语义”的人,才能发现这个缺口。另外,搜索入口常带一个“短词过滤”(如长度 <= 2 才拒绝),而恰好跨过该阈值的纯通配符输入仍能生效——这提醒我们“巧合安全”(靠长度/特征碰巧堆住)并不可靠。

三、影响版本与修复

  • 影响版本:phpMyFAQ < 4.1.1。
  • 官方修复:在 Search.php 的 searchCustomPages() 中,在拼接 LIKE 参数前对输入额外转义通配符(将 |、%、_ 分别替换为 ||、|%、|_),并在 SQL 中加上 ESCAPE '|' 子句。两行改动,本质是把通配符从“操作语义”降级为“字面字符”,使 % 和 _ 不再被当作通配符解释。
  • 升级:直接升级到 phpMyFAQ >= 4.1.1;不具备升级条件时,可按上述思路在自定义搜索代码中手动热修复。

四、通用防护模板

凡是将用户输入拼入 LIKE 子句的代码,都应把“界定符转义”和“模式元字符转义”当作两件事分开处理:

  1. 先转义通配符与转义符本身:把 |(或选定的 ESCAPE 字符)、%、_ 映射为“转义序列”;
  2. 再交给参数化/转义进入数据库;
  3. 在 SQL 中声明 ESCAPE 子句,确保数据库按预期降级元字符。

此外还应配合纵深:搜索等公开入口不应无差异地返回全部内部数据,应在查询层叠加权限/可见性过滤,避免“匹配得到”等于“可以读”。

五、检测与审计思路

  • 代码审计:重点排查所有使用 LIKE / 模糊查询的位置,确认是否存在“只转义界定符、未处理通配符”的模式;不能因为看到 real_escape_string 就一律判定安全。
  • 流量/日志:关注搜索关键词中大量或纯粹由 %、_ 组成、却又能返回异常多结果的请求,作为可能的匹配范围放大信号。
  • 测试验证:在自有、隔离环境中验证修复是否将通配符正确降级为字面字符(正常关键词仍匹配、通配符不再触发全量匹配),而非直接对线上系统测试。

小结

这个漏洞的教学价值不在于“杀伤力”,而在于提醒我们:转义/参数化解决的是“语法结构”,而 LIKE 有自己的“匹配语义”。把安全边界仅定在“防字符串提前闭合”是不够的——凡是存在独立元字符语义的上下文(模式匹配、正则、排序字段等),都需要单独确认输入是否被恰当降级为字面量。


本文仅用于漏洞原理分析、代码审计与安全加固之目的。复现与验证均应在自有或经授权的隔离环境中开展,遵守《中华人民共和国网络安全法》及相关法律法规,不得用于任何未经授权的越权数据获取行为。

相似文章
相似文章
小程序二维码
 全屏