宽字节注入 原理在下方
目录
less-32
宽字节注入原理
mysql 在使用 GBK 编码的时候,会认为两个字符为一个汉字,例如%aa%5c 就是一个汉字(前一个 ascii 码大于 128 才能到汉字的范围)。我们在过滤 ’ 的时候,往往利用的思路是将‘转换为\’(转换的函数或者思路会在每一关遇到的时候介绍)。
PHP 自带一些转义特殊字符的函数,如addslashes()
,mysql_real_escape_string()
,mysql_escape_string()
等,这些函数可用来防止 SQL 注入。
如id=1'or'1'='1
,单引号本用来闭合语句,这些函数会自动转义这些闭合的单引号,在这些单引号前面加上转义符\
,变为1\'or\'1\'=\'1
,如此在 SQL 查询中是一个普通的字符串,不能进行注入。
而网站在过滤'
的时候,通常的思路就是将'
转换为\'
,因此我们在此想办法将'
前面添加的\
去掉,一般有两种思路:
-
%bb吃掉
\
如果程序的默认字符集是GBK
等宽字节字符集,就有可能产生宽字节注入,绕过上述过滤。
若在 PHP 中使用mysql_query("set names gbk")
将默认字符集设为GBK
,而使用addslashes()
转义用户输入,这时如果用户输入%bb%27
,则addslashes()
会在%27
前面加上一个%5c
字符,即转义字符\
。
而 MySQL 在使用GBK
编码时,会认为两个字符为一个汉字,%bb%5c
是一个宽字符(前一个 ASCII 码大于 128 才能到汉字的范围),也就是籠
,也就是说%bb%5c%27
=籠'
,这样单引号就未被转义能闭合语句,从而产生 SQL 注入。%bb
并不是唯一一个可以产生宽字节注入的字符,理论上%81
-%FE
均可。 -
过滤
\'
中的\
构造%bb%5c%5c%27
,addslashes()
会在两个%5c
和%27
前都加上\
即%5c
,变为%bb %5c%5c %5c%5c %5c%27
,但宽字符集认为%bb%5c
是一个字符即籠
,则变为%bb%5c %5c%5c %5c%5c %27
即籠\\\\'
,四个\
正好转义为两个\
,即'
未被转义。这也是 bypass 的一种方法。