0x01 原理
-
单字节字符集: 所有的字符都使用一个字节来表示,比如 ASCII 编码。
-
多字节字符集: 在多字节字符集中,一部分字节用多个字节来表示,另一部分(可能没有)用单个字节来表示。
-
两位的多字节字符有一个前导字节和尾字节。 在某个多字节字符集内,前导字节位于某个特定范围内,尾字节也一样。
-
UTF-8 编码: 是一种编码的编码方式(多字节编码),它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
-
常见的宽字节: GB2312、GBK、GB18030、BIG5、Shift_JIS GB2312 而转义符 \ 及
%5c
和 其他字节 比如%df
就可以构成一个汉字
0x02 条件
当前端为utf-8 ,数据库设置GBK(或者其他多字节字符集)
由于 传入参数需要转码操作 就会使 %df%5c
看成一个汉字
0x03 演示
http://localhost/sqlilabs/Less-32/?id=-1%df%27 union select 1,group_concat(username) ,group_concat(password) from security.users--+
0x04 防止
-
就是先调用
mysql_set_charset
设置当前字符集为gbk,再调用函数mysql_real_escape_string
来过滤用户输入。 -
还可以把
character_set_client
设置为binary二进制 ,当我们的mysql接受到客户端的数据后,会认为他的编码是character_set_client,然后会将之将换成character_set_connection的编码,然后进入具体表和字段后,再转换成字段对应的编码。然后,当查询结果产生后,会从表和字段的编码,转换成character_set_results编码,返回给客户端。
对于宽字节编码,有一种最好的修补就是:
-
使用mysql_set_charset(GBK)指定字符集
-
使用mysql_real_escape_string进行转义
原理是,mysql_real_escape_string与addslashes的不同之处在于其会考虑当前设置的字符集,不会出现前面e5和5c拼接为一个宽字节的问题,但是这个“当前字符集”如何确定呢?
0x05 补充
1、当 ' "
被转义是 后面用到时,可将字符串转成16进制 从而绕过 不使用 引号
0x06 参考
Q.E.D.