原理:宽字节注入是利用mysql的一个特性,mysql在使用GBK编码(GBK就是常说的宽字节之一,实际上只有两字节)的时候,会认为两个字符是一个汉字(前一个ascii码要大于128,才到汉字的范围),而当我们输入有单引号时会自动加入\进行转义而变为\'(在PHP配置文件中magic_quotes_gpc=On的情况下或者使用addslashes函数,icov函数,mysql_real_escape_string函数、mysql_escape_string函数等,提交的参数中如果带有单引号('),就会被自动转义\',使得多数注入攻击无效),由于宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象,将后面的一个字节与前一个大于128的ascii码进行组合成为一个完整的字符(mysql判断一个字符是不是汉字,首先两个字符时一个汉字,另外根据gbk编码,第一个字节ascii码大于128,基本上就可以了),此时单引号(')前的\就被吃了,我们就可以使用单引号(')了,利用这个特性从而可实施SQL注入的利用。
这里我们以 sqli-labs-master第32关为例:
第一步判断是否存在注入点,我们这里省略不做累赘;
第二步判断闭合情况,我们输入单引号,这时你会发现页面显示得是 1\',而不是1',很明显单引号被网站转义了!
这时候我们可以在单引号的前面加上%df,页面正常报错
加上闭合符,页面回显正常
接下来我们继续判断页面的列数及显示位
接下来就可以曝数据库名、版本等信息了
但到了曝数据表的时候,数据库名因为需要加上单引号又被转义了,这时你会发现即使再加上前面我们说过的%df也无效了。那怎么办?
我们可以将目标字符串转成16进制编码,这时字符串就不需要单引号来保护它了,而且编码后还需要在字符串前加上0X,
这样语句就被成功执行了。同理可以继续曝数据库的列名及其他信息!!