以下为原文摘抄:
因为本人在阅读答案时,有很多地方不明白的。在多次阅读之后,决定将原文摘抄下,并在不懂的地方加上笔记。
题目提示:通过注入获得flag值。
点开题目,又是一个简洁的界面让我一脸懵逼(0.0)
好吧,开始我们的注入之旅。
首先,随便往框里面输入字符和数字,发现当输入1、2、3的时候有查询结果。
接下来进行注入的第一步测试,输入一个带单引号的数据,目的是测试是否对构造SQL的字符串进行了过滤。当把带有单引号的数据(如输入 1')提交以后,我们得到了错误的返回。
这意味着我们这段“有害”的输入是被直接作为SQL语句了。
得到这个结果后我们可以猜测可能后台的代码是一个普通的select语句:
select name where id = 'content'
当然这只是个简单的猜测,肯定还是会有很多的其他过滤,但这个结果也侧面表现了我们可以通过开闭合单引号来进行我们的注入。
接下来我们进行第二步的过滤测试,关键字过滤。
我们将一些带有SQL关键字的语句输进去,发现有用的关键字几乎都被过滤掉了。
输入了大多数的关键字就剩下了delect和or,这个可怕(0.0)。
接下来就是空格过滤。
小编运气也比较好,在之前的第一步字符测试中,小编记得当时随手输入了一次andone,自己喜欢的美国街球品牌,惊奇的发现这里的and关键字并没有被过滤.
这里,我输入andone结果还是被过滤,和其他被过滤的关键字一样。怎么就没被过滤?
那也就是说这里的关键字过滤实际上是过滤后面带有一个空格的关键字(这我能理解,比如 select 这样或被过滤 ),仔细回忆刚刚我们的关键字过滤,最后的结果是“1 delect or”很短,也从而证明了过滤的关键字都是带有后面一个空格且过滤的过程也将后面的空格一起过滤掉了(确实,poc = 1 delect or andand select union,首先是给参数 1,不然无法构成正确的sql,无法正确执行,也就不明白到底过滤了什么)。
实验一下果真如此:
那么我们只需要想办法绕过这个关键字后面的空格过滤就能够达到我们的注入目的。
绕过空格的方法有很多:+、%0a、%0b、/****/……这里小编采用/**/的方式进行过滤。
绕过空格,是指什么呢?绕过空格过滤?提供的方式绕过,原理又是什么?https://blog.csdn.net/acsuccess/article/details/69360931
简单的来说,就是利用这个字符去代替我们本想输入的空格。
我在看别人题解的时候还发现有人通过写两遍关键字两遍空格的形式来进行过滤,比如写“andand ”这样过滤掉其中的“and ”后剩下的刚刚好还能组成一个“and ”。这***也行,人才啊!(^ O ^)。
过滤问题暂时就告一段落,接下来我们要绕过这些过滤去注入得到我们想要的答案。
首先,我们得确定表名。
利用单引号的开闭性,我们可以这样去确定数据库名表名字段名这些查询必须的东西了。
(1)数据库名:
我们通过select database()来确定当前的数据库名。
1' union//select//database()'
1' union//select//database()'
1' union//select//database()'
通过这句话我们能够得到数据库名为web1:
等一下,这个'符号为什么要在1和database()后面加,在真正的查询当中,代表着什么?我明白了,这里的1是sql里面的参数,那也不对啊,那这样的话,意思本来就是要把整个输入带入sql执行的啊,为什么还要加上单引号?哦,明白了,他1后面的单引号,是为了闭合,而后面的union select database()就是为了跟在这个输入之后,拼成sql语句的。通过单引号闭合,就是这个原理,你明白了么?
桥带麻袋,
我输入
1' union//select//databse()'变成了这个样子,web1就出来了?
为啥
明白了,这个也可以查出来当前的数据库是哪一个?换个poc:1' union/ /select//LEN()'
就会出现:
这里的len()是随便写的,加上()是为了告诉我们在哪个数据库中没有这个方法的,我们要的就是这个数据库名
(2)表名:
在MySQL中有一张表information_schema,这张表存储了MySQL服务器中所有的信息,如数据库名,数据库的表,表栏的数据类型与访问权限等。简言之,这台MySQL服务器上,到底有哪些数据库、各个数据库有哪些表,每张表的字段类型是什么,各个数据库要什么权限才能访问,等等信息都保存在information_schema表里面。
那么接下来我们对这张表进行查询来获取我们已知的当前数据库的表。
1' union//select//table_name from//information_schema.tables//where//table_schema//='web1
然而惊奇的发现,这句话竟然报错了!!!???
稍等一下,这里的单引号,我又不是很明白了,在=后之后加单引号?看了报错信息,web1竟然有单引号?这里并不是很清楚
没道理啊,之前也测试过了关键字之类的过滤情况,难道出现了我们之前没有测试过的关键字被过滤了?
观察报错信息,信息端只有=后面的信息,难道是=前面的这个table_schema这个字段被强制过滤了吗?
信息端只有 = 后面的信息,为什么就想到这里table_schema被过滤了?有原理?还是仅仅是猜测?
测试一下,果然如此:
poc: 1' table_schema'
table_schema这个字段被强制过滤了。
既然过滤关键字后面的空格的方法这里不能用,那么我们用之前说到的通过两次关键字拼接的方法能不能搞定呢:
1' union//select//table_name from//information_scheminformation_schemaa.tables//where//table_schemtable_schemaa//='web1
可是道高一丈啊,这里我们发现没有访问的权限:
那么接下来该怎么办呢,这里小编的想法比较单纯,我想的是,或许表的个数不会太多,那么我们干脆把全部得到,然后再一个一个去试就行了,但是结果有点让我大跌眼镜。
poc: 1' union//select//table_name from//information_schema.tables//where/**/' 1' ='1
这里又是不太明白,这个单引号到底是怎么玩的?而且,每次用这个命令去测,也只是相同的一个表名啊,怎么会把所有的都试出来呢?
结果多的离谱,一个一个去试感觉还是略显麻烦,不过现在小编也想不出什么其他的好办法了(T.T)。
就没有其他办法了么?
不过在这一堆表名中有一个表名叫flag:
[图片上传失败...(image-d2a059-1550628231563)]
如果不出意外的话,这个应该就是我们的目标吧(纯属猜的2333)。
那么接下来我们就需要去确定字段名,确定字段名一样的思路:
幸运的是,这次我们得到了它的字段:
[图片上传失败...(image-1a573b-1550628231563)]
这两个字段中,很明显我们的目标就是flag这个字段了吧(小小的吐槽一句,这里居然表名字段名都是flag,真的很好奇那些题解里写猜测可得的……)。
得到这个之后加上之前的绕过空格关键字过滤的方法书写一下内容得到答案:
1' union//select//flag from//flag where//'1'='1
[图片上传失败...(image-6334e7-1550628231563)]
这道题虽然写的难度中,分值也只有10分,但是小编做这题从查阅SQL语法,到学习SQL注入,到进行实战花了3天时间,当然因为很多人的题解写的又短又莫名其妙,中间还不乏一些完全没思路的猜测和没原理的结论,对小编起到了一些反面作用,不知道大家有没有这样的感受。因此小编全方位详细的分析了整道题,这篇博客小编也写了一下午+一晚上,希望对大家有帮助(0.0)。
另外,庆祝小编CSDN博客排名进入前10000名!谢谢大家的支持,我会继续努力的(O)。