如何修复基于宽字节(GBK编码)的特殊SQL注入漏洞?

P粉602998670

P粉602998670

2026-06-30

418人浏览

原创

set names 'gbk'会触发宽字节注入,因其仅设置character_set_client等会话变量,未同步连接层编码上下文,导致addslashes()按单字节转义('→%5c%27),而mysql用gbk解析时将%df%5c组合成汉字,“吃掉”反斜杠使%27逃逸;必须改用mysqli_set_charset()或set character_set_client=binary等方案对齐编码。

如何修复基于宽字节(gbk编码)的特殊sql注入漏洞?

为什么 set names gbk 会触发宽字节注入

因为 SET NAMES 'gbk' 只修改了 MySQL 的 character_set_clientcharacter_set_resultscharacter_set_connection,但没真正绑定连接层的字符集语义。PHP 调用 addslashes() 时按单字节处理(比如把 '\',即 %27%5c%27),而 MySQL 在解析时把前面一个高位字节(如 %df)和 %5c 拼成一个 GBK 宽字符(如 “運”),导致 %5c 被“吃掉”,%27 逃逸成裸单引号。

mysql_set_charset() 和 mysqli_set_charset() 是必须替换的点

这两个函数不仅发 SET 命令,还会同步设置连接层的字符集上下文,让 MySQL 在接收数据时严格按指定编码解析,避免宽字节“吞字”行为。不替换 SET NAMES 就等于没修。

byte-units-master转换字节单位的PHP库
byte-units-master转换字节单位的PHP库

byte-units-master转换字节单位的PHP库

下载
  • mysql_set_charset("gbk", $conn)(已废弃,仅用于遗留代码)
  • mysqli_set_charset($conn, "gbk")(推荐,需在 mysqli_real_escape_string() 前调用)
  • 如果用 PDO,必须显式设置 PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4",且不能只靠 DSN 中的 charset=gbk

mysql_real_escape_string() 不能替代预编译,但它是宽字节场景下的兜底手段

该函数内部会读取当前连接的实际字符集(由 mysqli_set_charset() 设置),再做符合该编码规则的转义——比如对 GBK,它知道 %df%5c 是合法双字节,不会盲目拼接反斜杠。而 addslashes() 完全无视编码,纯字节流操作,必然出问题。

  • 必须确保 mysqli_real_escape_string() 调用前,连接已通过 mysqli_set_charset() 设定好字符集
  • 若传入空连接或未初始化连接,函数返回 false,容易被忽略导致绕过
  • 它只防字符串型注入,数字型参数仍需 intval() 或参数化

character_set_client=binary 是最硬核的防御方式

在查询前执行 mysqli_query($conn, "SET character_set_client = binary"),会让 MySQL 把客户端输入当作原始字节流处理,不再尝试按 GBK 解码。此时 %df%5c%27 不会被识别为“運'”,而是三个独立字节,MySQL 直接报错或截断,无法构成有效 SQL 语法。

  • 这个设置只影响当前 query,需每次查询前重设(或封装进统一 query 函数)
  • 它不解决乱码问题,但能彻底阻断宽字节注入链路
  • 注意:不能和 SET NAMES 混用,否则后者会覆盖前者
关键点在于:宽字节注入不是 PHP 层漏了过滤,而是字符集声明与实际转义逻辑脱节。修复必须从连接层编码一致性切入,任何只改 SQL 拼接方式或只换过滤函数的方案,只要底层还是 SET NAMES gbk + addslashes(),就等于门没锁死。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

2401

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

447

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

612

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3921

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

1300

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

3518

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

3393

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

638

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

525

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程