Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >php宽字节注入,[投稿]宽字节注入详解

php宽字节注入,[投稿]宽字节注入详解

作者头像
全栈程序员站长
发布于 2022-11-04 09:39:35
发布于 2022-11-04 09:39:35
3.5K0
举报

前言

mysql中,用于转义的函数有addslashes,mysql_real_escape_string,mysql_escape_string等,还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性。

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

Default

<meta charset=utf8>

1

<metacharset=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设定值。

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

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

PHP测试代码:

Default

<!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/>”;

}

?>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

<!DOCTYPEhtml>

<metacharset=”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/>”;

}

?>

Default

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

1

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

是可以执行成功的!

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

解析过程:

Default

$_GET[‘sql’] 经过 addslashes编码之后带入了‘\’

1、root%df%5C%27%20or%201=1%23

2、带入mysql处理时使用了gbk字符集

%df%5c -> 運 成功的吃掉了%5c

%27 -> ‘ 单引号成功闭合

1

2

3

4

5

6

7

8

9

10

$_GET[‘sql’]经过addslashes编码之后带入了‘\’

1、root%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属性来对待传入的字符串,因此可以根据当前字符集来进行过滤。

同理可得

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

转码函数

mb_convert_encoding()

iconv()

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

Default

<!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);

}

?>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

<!DOCTYPEhtml>

<metacharset=”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);

}

?>

Default

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

1

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时转码安全。

另外:

当改变编码方向时user = iconv(‘UTF-8’, ‘gbk’,user);

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

例如:

Default

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

1

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

赏金发放情况:本文获得赏金100RMB,已于4.3日发放到作者账号。

征稿启事:91RI一直相信“你不与人分享,谁与你分享”,分享的确是件非常有意义的事情。为了让优秀的同学有地方分享自己的独到见解,也为了让更多同学从分享中受益,同时我们也希望给那些愿意分享的小伙伴们一点点心意作为感谢,所以我们隆重了推出“有奖征文”活动!本次活动的详情可以围观《征稿启事》

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/181945.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
浅析白盒审计中的字符编码及SQL注入
在freebuf上莫名地被喷,可能是因为被喷让人气上来了,最后得到的金币比前一篇文章更多。塞翁失马,焉知非福?
phith0n
2020/10/15
8970
宽字节注入原理剖析总结
本公众号提供的工具、教程、学习路线、精品文章均为原创或互联网收集,旨在提高网络安全技术水平为目的,只做技术研究,谨遵守国家相关法律法规,请勿用于违法用途,如果您对文章内容有疑问,可以尝试加入交流群讨论或留言私信,如有侵权请联系小编处理。
网络安全自修室
2022/01/24
4.6K0
宽字节注入原理剖析总结
宽字节注入原理分析[通俗易懂]
如果一个字符的大小是一个字节的,称为窄字节;如果一个字符的大小是两个字节的,成为宽字节
全栈程序员站长
2022/11/04
2K0
宽字节注入原理分析[通俗易懂]
addslashes防注入的绕过案例(AFSRC获奖白帽子情痴)
代码审计中遇到的一些绕过addslashes的案例 From ChaMd5安全团队核心成员 无敌情痴 MMMMM叫我写一篇文章发到公众号,然而我是ChaMd5安全团队第一弱的大菜逼,于是就写篇基础的审计文章,在实际情况中,会出现各种各样的绕过防注入的手法,我这里只是列举了我在实际审计中遇到的比较常见的绕过方法。 前段时间审计过不少PHP开源系统,而很多PHP开源系统针对sql注入都喜欢用addslashes来防止注入,也就是把’ “ %00 这些符号转义在前面加个\。 根
ChaMd5安全团队
2018/03/29
4K0
addslashes防注入的绕过案例(AFSRC获奖白帽子情痴)
代码审计day4
因为%df的关系, \的编码%5c被吃掉了,也就失去了转义的效果,直接被带入到mysql中,然后mysql在解读时无视了%a0%5c形成的新字节,那么单引号便重新发挥了效果
2020/08/19
3050
SQL注入实例学习待整理
注意:本文分享给安全从业人员,网站开发人员和运维人员在日常工作中使用和防范恶意攻击, 请勿恶意使用下面描述技术进行非法操作。
全栈工程师修炼指南
2022/09/28
4080
SQL注入实例学习待整理
​ 【SQL注入必学基础】--宽字节注入
二进制:计算机内部是由集成电路这种电子部件构成的,电路只可以表示两种状态——通电、断电,也就是使用二进制存储数据。因为这个特性,计算机内部只能处理二进制。那为什么我们能在计算机上看到字母和特殊字符呢?
Power7089
2020/07/27
1.1K0
​ 【SQL注入必学基础】--宽字节注入
宽字节注入讲解
我讨厌现在的自己,一边压抑着自己的情绪,一边装作没事的样子,一到深夜就彻底崩溃了,天亮后还要微笑面对生活。。。
全栈程序员站长
2022/11/04
6110
宽字节注入讲解
PHP升级到5.5+后MySQL函数及其Mysqli函数代替用法
由于MySQL扩展从php5.5开始弃用,所以以后不推荐大家再用MySQL扩展,请用MySQLi或PDO代替,以下是MySQL对应的MySQLi函数(绿色字体)供大家参考。(注:PHP手册上的有误,这里是最准的)
IT工作者
2021/12/20
1.1K0
最新宽字节注入攻击和代码分析技术
访问id=1',页面的返回结果如图4-51所示,程序并没有报错,反而多了一个转义符(反斜杠)。
Ms08067安全实验室
2023/10/02
3020
最新宽字节注入攻击和代码分析技术
【作者投稿】宽字符注入详解与实战
SQL语句是SELECT * FROM news WHERE tid='{$id}',根据文章的id把文章从news表中提取出来,在$sql之前,我们只用了限制函数addslashes函数,对$id进行转义,只要我们输入参数在单引号中,就逃逸不出单引号的限制,从而无法注入。
信安之路
2018/08/08
1.6K0
【作者投稿】宽字符注入详解与实战
面试中碰到的坑之注入系列(2)
Test:什么是宽字节注入?怎么防止sql注入? 00x1 防止数字型sql注入 说到mysql宽字节注入之前要提的是php中常见的sql防护思路。 php是弱类型的语言,而弱类型的语言在开发中很容易出现数字型的注入,所以对于这方面的防御,应该要有严格的数据类型。 比如:用is_numeric()、ctype_digit()判断字符类型。或者自定义一个check_sql函数对select union关键字进行过滤。 这类的防御比较简单,但是字符型的防注入就比较麻烦了。就是要将单引号
lonelyvaf
2018/06/07
1.2K0
PHP代码审计笔记--SQL注入
测试语句:id=1 UNION SELECT user(),2,3,4 from users
Bypass
2019/07/08
1.7K0
PHP代码审计笔记--SQL注入
2024全网最全面及最新且最为详细的网络安全技巧四 之 sql注入以及mysql绕过技巧 (4)———— 作者:LJS
对于传入的非法的 $_GET 数组参数名,PHP会将他们替换成 下划线 。经过fuzz,有以下这些字符:
盛透侧视攻城狮
2024/10/21
1140
2024全网最全面及最新且最为详细的网络安全技巧四 之 sql注入以及mysql绕过技巧 (4)———— 作者:LJS
什么是宽字节注入_百分号两个字节
原理:宽字节(两字节)带来的安全问题主要是吃ASCII字符(一字节)的现象,使用一些特殊字符来”吃掉“经过转义符 “ \ ” 。
全栈程序员站长
2022/11/04
4680
宽字节注入与二次注入[文末彩蛋]
在进行php 连接mysql 时,当设置”ser character_set_client=gbk” 时会导致一个编码转换的注入问题,也就是熟悉的宽字节注入
天钧
2019/07/25
5840
PHP全栈学习笔记17
打开C:\wamp\apps\phpmyadmin3.5.1下的配置文件:config.inc
达达前端
2019/07/03
2.3K0
PHP全栈学习笔记17
宽字节注入是什么_sqlmap宽字节注入
在一个CTF练习的网站,看到了一个宽字节注入的题目,我是一个web萌新,没什么经验,一开始也没有想到是宽字节,还是一位朋友给我提到的,让我猛然大悟,咳咳。。。做一些总结。
全栈程序员站长
2022/11/04
1.8K0
宽字节注入是什么_sqlmap宽字节注入
PHP处理MYSQL注入漏洞
SQL注入漏洞为PHP研发人员所熟知,它是所有漏洞类型中危害最严重的漏洞之一。SQL注入漏洞,主要是通过伪造客户端请求,把SQL命令提交到服务端进行非法请求的操作,最终达到欺骗服务器从而执行恶意的SQL命令。
袁某人
2021/12/28
2.3K0
PHP处理MYSQL注入漏洞
1.4.1-SQL注入防御绕过-宽字节注入
MySQL在使用GBK编码的时候,会认为两个字符为一个汉字。 使用%df’进行编码,两个字符组合,认为是一个汉字。 注:前一个Ascii码大于128才能到汉字的范围
tea9
2022/07/16
1.1K0
1.4.1-SQL注入防御绕过-宽字节注入
相关推荐
浅析白盒审计中的字符编码及SQL注入
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文