[强网杯 2019]随便注

这题我太菜了,根本注不出来,就只能注出个字段数量,他关键过滤了select,没法联合查询了,查解后发现,需要使用堆叠注入,其中涉及到一些新的SQL语法,所以这篇就当做学习篇了。

1.什么是堆叠注入?

Stacked injections(堆叠注入)从名词的含义就可以看到应该是一堆 sql 语句(多条)一起执行。而在真实的运用中也是这样的, 我们知道在 mysql 中, 主要是命令行中, 每一条语句结尾加; 表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做 stacked injection。

2. 堆叠注入原理

在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。

而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?

区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。

例如以下这个例子。

用户输入:1; DELETE FROM products服务器端生成的sql语句为: Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。

3. 实验过程

由于select被过滤,所以这题主要使用show命令来查看数据库结构

查看数据库名

show databases;

image

发现他有6个数据库

查看表名

show tables;

image

可以发现当前数据库有两张表:1919810931114514、words

查字段名

下面就可以针对每一张表去查看对应的结构信息了,这里有两种方法可以使用:

1)desc命令:查看表结构的详细信息,此处desc是describe的缩写,他的用法是: desc 表名/查询语句

2)show命令:show columns from 表名

下面分别用这两种方式查字段名

image

注:这里desc后面的内容要用反引号包裹起来,不然查不到内容

image

查完后可以得知在表1919810931114514中存在flag字段,所以后面的目标就是查看这个字段下的内容

查值

上网查了很多方法,没有看到可以用命令查出表里的数据的,都必不可少的使用select语句,所以这里直接查看表内数据应该是没希望了。

这里就需要变通一下了,虽然我们不能自己构造select语句,但是这道题在一开始他就给了我们一个输入框,而这个输入框肯定是对应着后台的一个查询语句的,估计类似于:select * from 某表,那这里只要知道了这个表名,我们就可以使用偷天换日大法,通过修改表名或字段名的方法,让他去查我们想要的数据。回顾刚刚查表的操作,我们查到了两张表(至于这两张表是属于哪个数据库的,这里看来是无关紧要的),在表1919810931114514中只有一个flag字段,所以肯定不会是这个表名,那剩下的无疑就是words表了,words表中存在两个字段id和data,正好对应我们的查询结果:

image

分析到这里就可以明确下一步该干嘛了,就是要把我们想查的那个字段名和表名改为id和words,这样在首页查询时就能显示出其中的值了(注意表名不能重复,所以还要将words表改名,另外字段名必须为id,因为他是根据id进行查值的)。

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);

改完后回首页查值,直接查是看不到东西的,因为此时的id值已经变成flag了,所以需要使用or 语句构造永真值,来查看表内所有数据:1' or 1=1 --+

image

注意

切记不要改错字段名,否则就会:

image

这会造成什么后果呢?

你想他的SQL语句是这样的:select * from words where id=1

一旦你把flag改错为data,表中没有了id字段,那你现在唯一可以利用的这条SQL语句就会报错,一旦报错了,你还想用堆叠注入改回来就没这么简单了,因为前面的SQL语句报错,后面的语句也就不会执行了,最后这个注入点就会变得难以利用,然后你就不得不再想其他方法。

4. 预编译法

上面那个靶场已经被我整废了,我们重置靶场测试第二种方法

预编译的相关语法如下:

set用于设置变量名和值
prepare用于预备一个语句,并赋予名称,以后可以引用该语句
execute执行语句
deallocate prepare用来释放掉预处理的语句

构造payload如下:

-1';set @sql = CONCAT('se','lect * from `1919810931114514`;');prepare stmt from @sql;EXECUTE stmt;#

拆分:
-1';
set @sql = CONCAT('se','lect * from `1919810931114514`;');
prepare stmt from @sql;
EXECUTE stmt;
#

结果如下:

image

检测set和prepare,需要绕过,方法:改大小写

结果:

image

参考资料

  1. https://zhuanlan.zhihu.com/p/78989602
  2. https://www.cnblogs.com/backlion/p/9721687.html
posted @ 2021-09-24 10:59  Sentry_fei  阅读(31)  评论(0编辑  收藏  举报