转宽字节注入详解

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 在mysql中,用于转义的函数有addslashes,mysql_real_escape_string,mysql_escape_string等, 还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性。

 

在mysql中,用于转义的函数有addslashes,mysql_real_escape_string,mysql_escape_string等,

还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性。

首先,宽字节注入与HTML页面编码是无关的,笔者曾经看到

<meta charset=utf8>

就放弃了尝试,这是一个误区,SQL注入不是XSS。虽然他们中编码的成因相似,不过发生的地点不同。

很多网上的材料都说程序使用了宽字节来处理程序,却又不指出具体是指什么程序。本文就介绍一下具体

漏洞发生的原理与简单的利用。在这里我们限定使用的语言是PHP5.4,数据库MYSQL5.6。

 

涉及到的一些概念

字符、字符集与字符序

字符(character)是组成字符集(character set)的基本单位。对字符赋予一个数值(encoding)

来确定这个字符在该字符集中的位置。

字符序(collation)指同一字符集内字符间的比较规则。

UTF8

由于ASCII表示的字符只有128个,因此网络世界的规范是使用UNICODE编码,但是用ASCII表示的字符使用UNICODE并不高效。

因此出现了中间格式字符集,被称为通用转换格式,及UTF(Universal Transformation Format)。

宽字节

GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。

宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象。

 

MYSQL的字符集转换过程

1. MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;

2. 进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下:

• 使用每个数据字段的CHARACTER SET设定值;

• 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准);

• 若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值;

• 若上述值不存在,则使用character_set_server设定值。

  1. 将操作结果从内部操作字符集转换为character_set_results。

重点:宽字节注入发生的位置就是PHP发送请求到MYSQL时字符集使用character_set_client设置值进行了一次编码。

 

PHP测试代码:

复制代码
<!DOCTYPE html> <meta charset="gbk"><!--仅用于基础的显示,换成utf8也行就是不好看--> <?php error_reporting(0); $conn = mysql_connect('127.0.0.1','root',''); mysql_select_db('mysql',$conn); mysql_query("set names gbk"); //不安全的编码设置方式 $res = mysql_query("show variables like 'character%';"); //显示当前数据库设置的各项字符集 while($row = mysql_fetch_array($res)){ var_dump($row); } $user = addslashes($_GET['sql']); //mysql_real_escape_string() magic_quote_gpc=On addslashes() mysql_escape_string()功能类似 $sql = "SELECT host,user,password FROM user WHERE user='{$user}'"; echo $sql.'</br>'; if($res = mysql_query($sql)){ while($row = mysql_fetch_array($res)){ var_dump($row); } } else{ echo "Error".mysql_error()."<br/>"; } ?>
复制代码
http://localhost/xl.php?sql=root%df%27%20or%201=1%23

是可以执行成功的!

URL解码sql=rootß’ or 1=1#

解析过程:

复制代码
$_GET[‘sql’] 经过 addslashes编码之后带入了‘\’ 1root%df%5C%27%20or%201=1%23 2、带入mysql处理时使用了gbk字符集 %df%5c ->  成功的吃掉了%5c %27 ->  单引号成功闭合
复制代码

执行了插入的sql语句。

 

怎么吃的:

GBK编码,它的编码范围是0x8140~0xFEFE(不包括xx7F),在遇到%df(ascii(223)) >ascii(128)时自动拼接%5c,

因此吃掉‘\’,而%27、%20小于ascii(128)的字符就保留了。

补充:

GB2312是被GBK兼容的,它的高位范围是0xA1~0xF7,低位范围是0xA1~0xFE(0x5C不在该范围内),因此不能使用编码吃掉%5c。

其它的宽字符集也是一样的分析过程,要吃掉%5c,只需要低位中包含正常的0x5c就行了。

 

安全过滤

上文中代码使用了mysql_query(“set names gbk”)来设置编码,其实在mysql中是推荐mysql_set_charset(“gbk”);函数来进行编码设置的,

这两个函数大致的功能相似,唯一不同之处是后者会修改mysql对象中的mysql->charset属性为设置的字符集。

同时配套的过滤函数为mysql_real_escape_string()。上面代码中列出了几个过滤的函数,他们之间的区别就是mysql_real_escape_string()

会根据mysql对象中的mysql->charset属性来对待传入的字符串,因此可以根据当前字符集来进行过滤。

具体差别可参考:http://www.laruence.com/2010/04/12/1396.html

同理可得

由上文可得宽字节注入是由于转编码而形成的,那具有转编码功能的函数也成了漏洞的成因。

转码函数

mb_convert_encoding()

iconv()

 以下用iconv()来演示,修改上面的代码:

复制代码
<!DOCTYPE html> <meta charset="gbk"> <?php error_reporting(0); $conn = mysql_connect('127.0.0.1','root',''); mysql_select_db('mysql',$conn); mysql_set_charset("utf8"); //推荐的安全编码 $user = mysql_real_escape_string(($_GET['sql'])); //推荐的过滤函数 $user = iconv('GBK', 'UTF-8',$user); $sql = "SELECT host,user,password FROM user WHERE user='{$user}'"; echo $sql.'</br>'; $res = mysql_query($sql); while($row = mysql_fetch_array($res)){ var_dump($row); } ?>
复制代码

 

 

http://localhost/xl.php?sql=root%e5%27or%201=1%23

同样可以执行成功,编码解析的过程依然如上。

 

总结一下漏洞成因:

代码一

1、使用了不安全的字符集设置函数与过滤函数。

2、漏洞发生在PHP请求mysql时使用character_set_client值进行一次转码。

代码二

1、使用了推荐的设置函数与过滤函数。

2、解析错误发生在iconv()函数转码时,GBK转向UTF8吃掉了“\”

3、PHP请求mysql时转码安全。

 

另外:

当改变编码方向时<spanstyle="display:inlineblock;position:relative;width:13.119em;height:0px;fontsize:116<spanstyle="display:inline−block;position:relative;width:13.119em;height:0px;font−size:116user=iconv(‘UTF−8′,‘gbk′,user);

通过访问http://localhost/xl.php?sql=root%e9%8c%a6可以带入一个\,进而注释掉单引号。

这种情况下需要两个参数来配合注入。

例如:

http://localhost/xl.php?sql=root%e9%8c%a6¶=%20or%201=1%23

总结:

宽字节注入跟HTML页面编码无关。

Mysql编码与过滤函数推荐使用mysql_real_escape_string(),mysql_set_charset()。

转编码函数同样会引起宽字节注入,即使使用了安全的设置函数。

 

参考文献

mysql字符集的设置:http://www.laruence.com/2008/01/05/12.html

原博文地址:https://www.cnblogs.com/ECJTUACM-873284962/p/8747543.html

 

 
您可以考虑给博主来个小小的打赏以资鼓励,您的肯定将是我最大的动力。

微信 支付宝
作者: 落花四月
关于作者:潜心于网络安全学习。如有问题或建议,请多多赐教!
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信我
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
存储 安全 Shell
1.10 内存ShellCode注入与格式化
ShellCode 的格式化与注入功能在实战应用中也尤为重要,格式化`Shellcode`是指将其转换为可执行的二进制格式,使其能够在内存中运行。注入`Shellcode`是指将格式化的`Shellcode`注入到另一个进程的内存中,以便在该进程中执行,此类功能也可算作`ShellCode`技术的延申功能。
154 1
|
6月前
|
JSON JavaScript Linux
有关于【该文件的字符编码需要在传输协议层声明,或者在文件中加入一个 BOM(字节顺序标记)】的另一种解决办法
有关于【该文件的字符编码需要在传输协议层声明,或者在文件中加入一个 BOM(字节顺序标记)】的另一种解决办法
2 字节的 UTF-8 序列的字节 2 无效 解决方法
2 字节的 UTF-8 序列的字节 2 无效 解决方法: 用记事本打开xml文件,另存为 编码 选择 UTF-8,保存替换掉之前的文件,解决问题博客内容仅代表个人观点,如发现阐述有误,麻烦指正,谢谢!
4161 0
|
6月前
|
关系型数据库 MySQL 数据库
宽字节注入讲解
宽字节注入讲解
51 1
|
SQL 安全 程序员
宽字节注入详解
宽字节注入详解
136 0
|
6月前
|
关系型数据库 MySQL 数据库
宽字节注入
宽字节注入
32 1
|
6月前
|
安全 关系型数据库 MySQL
MySQL注入 -- 宽字节注入
MySQL注入 -- 宽字节注入
44 0
|
6月前
|
数据库
22、宽字节注入
22、宽字节注入
35 0
|
6月前
|
数据库
小课堂 -- 宽字节注入
小课堂 -- 宽字节注入
25 0