SQL注入测试技巧TIP:再从Mysql注入绕过过滤说起

*本文原创作者:Zzzxbug,本文属FreeBuf原创奖励计划,未经许可禁止转载

对于mysql的注入,基本上是每一名web安全从业者入门的基本功,这里不多废话,结合本人无聊时在mysql上的测试,来谈一谈mysql在过滤某些特殊字符情况下的注入,因为是想到哪写到哪,文章比较散,各位大佬请绕过,和我一样的小白可以看一看,温故而知新,必有所获。

php查询mysql的后台脚本就不搭了,没有多大意义,直接从mysql控制台开始测试。首先从最简单的开始:

直接使用mysql系统库做测试:

我们假设在user后存在注入点:那么在利用order by获得列数后进行union注入:

现在开始增加难度,假设后端代码过滤了空格,我们可以替换空格的方法很多:/**/,0x0a,0x0b,0x0c,0x0d:

上图使用/**/替换空格

上图使用0x0a号字符替换空格,注意:按住alt键+小键盘输入10再松开alt键即可在控制台中输入ascii字符0x0a

上图使用0x0b号字符替换空格,注意:按住alt键+小键盘输入11再松开alt键即可在控制台中输入ascii字符0x0b

上图使用0x0c号字符替换空格,注意:按住alt键+小键盘输入12再松开alt键即可在控制台中输入ascii字符0x0c

上图使用0x0d号字符替换空格,注意:按住alt键+小键盘输入13再松开alt键即可在控制台中输入ascii字符0x0d,但因为在控制台中一旦输入0x0d,就会执行指令,所以这里只在union前输入了一次。

做到这里我们可能会想,除了这些字符外还有没有其它字符可以替换空格呢,我们fuzz一下:

将以上代码存为1.php,放入apache中网页访问,显示结果:

可以发现,除了我们刚刚使用的0x0a,0x0b,0x0c,0x0d外还有9号与160号字符可以替换空格(32号本身就是空格,35是注释符不能查询获得正确结果,9号是tab,刚刚漏了,至于160号字符为什么行,我也不知道,那位哥如果知道可以告诉大家)。

进一步思考:如果这些字符都被过滤了,有没有办法不依靠空格来注入呢,办法还是有的,看下面的语句:

在这个语句中:

利用了括号、反引号来隔离了sql关键词与库名表名列名,完成了注入。

接下来继续提高难度,我们的注入语句中有许多逗号,看了让人不爽,如果把逗号也过滤掉,我们有没有办法注入呢,方法还是有的,我们可以结合join语句和子查询的别名来替换逗号,看下面的语句

在这个语句中,我们利用join与别名,成功的避免使用逗号实现了注入:

玩到这里,我脑洞忽然大开:mysql的子查询别名是可以无限嵌套的么,像俄罗斯套娃一样,下面的语句可以无限扩展么,会不会出现溢出呢:

为了验证,我又进行了一次fuzz,将下面的代码存为2.php,放入apache中网页访问:

结果如下:

可以看到在嵌套64次后,mysql输出了”Too high level of nesting for select”的错误信息,也就是说我们最多用mysql进行嵌套子查询64层。

继续回到正题上,再来看刚刚的语句:

在库名、表名、列名不带空格、*、{、}等特殊符号的情况下(我猜想反引号的存在本来就是为了这类特殊库名表名列名准备的),语句中的反引号也可以用括号代替,变成下面的语句,这样即使过滤了反引号也可以实现注入:

如果存在宽字节注入,那么即使过滤了单引号,我们也可以注入,这时语句变成这样:

在注入点处使用宽字节绕过\,将后面的数据处替换成十六进制,来避免了单引号。

其他技巧:

某些web应用只取查询结果的第一行,这时可以使用group_concat()来获取完整数据,例如:

也可以多加几个条件判断来逐行获取所要的数据:

*本文原创作者:Zzzxbug,本文属FreeBuf原创奖励计划,未经许可禁止转载

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181206B1C4S300?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券