• 什么是窄字节和宽字节呢?
    当某字符的大小为一个字节时,称其字符为窄字节。
    当某字符的大小为两个字节时,称其字符为宽字节。

  • 宽字节注入适用于那种情况?
    针对'\的过滤

宽字节注入原理

所有英文默认占一个字节,汉字占两个字节
mysql在使用GBK编码时,会认为两个字符为一个汉字,例如%aa%5c就是一个汉字(前一个ascii码大于128才能到汉字的范围)。我们再过滤'的时候,往往利用的思路是将'转化为\',因此我们再次想办法将'前面的\除掉

  1. %df之所以能吃掉\是因为urlencode(\')=%5c%27,如果我妈在%5c%27前面添加%df,成%df%5c%27,而上面提到mysql在GBK编码方式的时候会将两个字节当作一个汉字,此时的%df%5c就被识别出一个汉字,而%27则作为一个单独的'放在外面。
  2. \'中的\过滤掉,例如构造%**%5c%5c%27的情况,后面的%5c会被前面的%5c给注释掉。这一世一种bypass的一种方法。

宽字节注入示例

  • 在sqli-labs的Less-32中
    yuaneuro的小站
    上述函数将'转为\',将\转化为\\,将"转化为\"。因此可以直接添加一个%df%5c吃掉,也可以添加%aa%5c\转义成普通的的反斜杠

payload

Less-32/?id=-1%aa%5c%27union%20select%201,database(),3--+

或者

Less-32/?id=-1%df%27union%20select%201,database(),3--+
  • 在sqli-labs的Less-33中
    yuaneuro的小站
    使用了addslashes()函数返回在预定义字符之前添加反斜杠的字符串
    方法还是和之前一样

  • 在sqli-labs的Less-34中
    是POST型的注入漏洞,同样也是将post过来的内容进行了'\的处理。

  • 因为GET型的方式我们是以url形式提交的,因此数据会让通过URLencode

  • 在这里,我们可以将utf-8转化成为utf-16或utf-32,例如将'转化为utf-16为�',我们就可以利用这个方法

yuaneuro的小站

username:�' or 1=1#
password:(随便输)

此时的sql语句为

SELECT username,password FROM users WHERE username='�' or 1=1

防御

再来说说如何防御

  1. 使用mysql_set_charset(utf8)指定字符集
  2. 使用mysql_real_escape_string进行转义
  3. 设置character_set_client=binary
最后修改:2020 年 04 月 24 日
如果觉得我的文章对你有用,请随意赞赏