SQL注入--宽字节注入

什么是宽字节

当某字符的大小为一个字节时,称其字符为窄字节
当某字符的大小为两个字节时,称其字符为宽字节
所有英文默认占一个字节,汉字占两个字节
常见的宽字节编码:GB2312,GBK,GB18030,BIG5,Shift_JIS等等


使用宽字节注入的前提

  1. 数据库使用了gbk编码
  2. 使用了过滤函数,将用户输入的单引号转义(mysql_real_escape_string,addslashes)
    这样被处理后的sql语句中,单引号不再具有‘作用’,仅仅是‘内容’而已,换句话说,这个单引号无法发挥和前后单引号闭合的作用,仅仅成为‘内容’,具体如下:
 select * from users where id = ' 1 ' ;
 
 若注入语句为:1' order by 2#
 
 通过过滤函数拼接到sql语句中变为:1\' order by 2#
 即:select * from users where id = ' 1\' order by 2#;

 使'失效

什么是宽字节注入

绕过对于用户输入单引号等特殊符号的转义处理,使转义符号与输入的字符结合形成一个新的字符,从而使单引号逃脱转义处理,进行注入。

要绕过这个转义处理,使单引号发挥作用,有两个思路:

  1. 让斜杠(\)失去作用:对斜杠(\)转义,使其失去转义单引号的作用,成为‘内容’
  2. 让斜杠(\)消失:宽字节注入

SQL注入--宽字节注入_第1张图片
当使用宽字节编码,如:GBK时,两个连在一起的字符会被认为是汉字,我们可以在单引号前加一个字符,使其和斜杠(\)组合被认为成汉字,从未达到让斜杠消失的目的,进而使单引号发挥作用

注意:前一个字符的Ascii要大于128,两个字符才能组合成汉字
例如:129=0x81,加%即可,即%81’


注入案例(来自pikachu的SQL宽字节注入)

通过%df与\组成汉字来使单引号逃逸,获取数据库名字
SQL注入--宽字节注入_第2张图片
获取表名
SQL注入--宽字节注入_第3张图片
获取数据库中第二张表的字段名

注意:本来这里应该是table_name=‘users’,但因为对单引号进行了转义处理,所以不能使用’user’
但是可以通过嵌套一个select来查询到表名

SQL注入--宽字节注入_第4张图片
获取字段值
SQL注入--宽字节注入_第5张图片


防御

  1. 先调用mysql_set_charset函数设置连接所使用的字符集为gbk,再调用mysql_real_escape_string来过滤用户输入
  2. 将character_set_client设置为binary(二进制)

SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary
这几个变量是什么意思?

当我们的mysql接受到客户端的数据后,会认为他的编码是character_set_client,然后会将之将换成character_set_connection的编码,然后进入具体表和字段后,再转换成字段对应的编码。然后,当查询结果产生后,会从表和字段的编码,转换成character_set_results编码,返回给客户端。
所以,我们将character_set_client设置成binary,就不存在宽字节或多字节的问题了,所有数据以二进制的形式传递,就能有效避免宽字符注入。

SQL注入--宽字节注入_第6张图片
许多内容参考自此

你可能感兴趣的:(Web攻击,SQL注入)