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

php宽字节注入,[投稿]宽字节注入详解前言在mysql中,用于转义的函数有addslashes,mysql_real_escape_string,mysql_escape_string等,还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性。首先,宽字节注入与HTML页面编码是无关的,笔者曾经看到Default<metacharset=utf8>1<metacharset=utf8>…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

前言

在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

是可以执行成功的!

53b1541e62b44cc140afcc593092f14a.png

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

}

?>

604203d4d3e7e0ab676b2ab140784284.png

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

b2e4c3fc2d844d6134207b2018b5377e.png

总结:

宽字节注入跟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.net/181945.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 怎么让联想计算机升级,联想电脑怎么升级win11?联想电脑升级win11的几种方法…

    怎么让联想计算机升级,联想电脑怎么升级win11?联想电脑升级win11的几种方法…最近刚发布的windows11的消息,但是很多朋友使用联想电脑的朋友不知道怎么升级win11。戴尔电脑升级win11的方法有很多,可以通过win10系统加入WINDOWS预览体验计划,这样就可以将win10升级到win11系统了,也可以采用自己下载win11镜像用u盘的方式升级到win11系统,下面小编就教大家几种将联想电脑升级win11的方法详细步骤。联想电脑升级win11方法一:官方升级法,…

    2022年5月20日
    116
  • idea2022激活码截至2022年【中文破解版】2022.02.01

    (idea2022激活码截至2022年)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月31日
    1.8K
  • 【安全】Web渗透测试(全流程)

    【安全】Web渗透测试(全流程)1信息收集1.1域名、IP、端口域名信息查询:信息可用于后续渗透IP信息查询:确认域名对应IP,确认IP是否真实,确认通信是否正常端口信息查询:NMap扫描,确认开放端口如果不会用Nmap,看这里:NMAP基础教程(功能介绍,安装,使用)发现:一共开放两个端口,80为web访问端口,3389为windows远程登陆端口,嘿嘿嘿,试一下发现:是Window…

    2022年6月29日
    29
  • linux_c之ioctl的FIONREAD参数

    linux_c之ioctl的FIONREAD参数ioctl是用来设置硬件控制寄存器,或者读取硬件状态寄存器的数值之类的。而read,write是把数据丢入缓冲区,硬件的驱动从缓冲区读取数据一个个发送或者把接收的数据送入缓冲区。FIONREAD就是返回缓冲区中有多少字节;ioctl(keyFd,FIONREAD,&b)得到缓冲区里有多少字节要被读取,然后将字节数放入b里面。接下来就可以用read了,read(keyFd,

    2022年7月23日
    19
  • python jinja2_Python模块学习 – jinja2

    python jinja2_Python模块学习 – jinja2转置 https www cnblogs com dachenzi p 8242713 html 模板要了解 jinja2 那么需要先理解模板的概念 模板在 Python 的 web 开发中广泛使用 它能够有效的将业务逻辑和页面逻辑分开 使代码可读性增强 并且更加容易理解和维护 模板简单来说就是一个其中包涵占位变量表示动态的部分的文件 模板文件在经过动态赋值后 返回给用户 gt 可以理解为渲染

    2025年5月21日
    4
  • 关于我妈的一切_networkmanager是什么服务

    关于我妈的一切_networkmanager是什么服务NetworkManager(NetworManager)是检测网络、自动连接网络的程序。无论是无线还是有线连接,它都可以令您轻松管理。对于无线网络,网络管理器可以自动切换到最可靠的无线网络。利用网络管理器的程序可以自由切换在线和离线模式。网络管理器可以优先选择有线网络,支持VPN。网络管理器最初由Redhat公司开发,现在由GNOME管理。1.查看NetworkManager…

    2022年10月4日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号