Less1-Error Based-Single quotes - Strings
第一关是基于字符串单引号的注入,有错误回显.
正常的参数是id=1,这时我们就能看到正确的结果返回
而当我们输入的是 id=1' 时,数据库就会报错,提示我们有错误,这时我们就知道id这个参数存在sql注入漏洞
在箭头所指的地方可以看到出错的位置提示是
'' (1')' LIMIT 0,1 ' // 其中最前面和最后面的两个单引号是显示时添加的,并不在查询语句中
其中括号括起来的是我们输入的参数,当我们数单引号的个数时可以发现是奇数个,说明有一个单引号没有被闭合掉,因此数据库报错,也把错误回显给我们.
因此我们可以猜测这里的sql查询语句应该是
select * from table_name where id= ' x ' LIMIT 0,1
其中table_name是数据库的名字,x是我们输入的参数,因此当我们输入 id=1' 时,mysql就会报错
这时如果我们输入的是 id=1'' (后面是两个单引号)时,返回的结果变回了正常的页面
其中 %27 是单引号的URL编码,同样地这时如果也有显示信息,将会是
'' 1'' ' LIMIT 0,1'
这时去数单引号的个数,是偶数个则所有单引号都闭合了,因此不会报错,页面返回正常.
另外,如果我们想要去掉多余的单引号 ' ,我们可以进行如下操作
后面的 ' --+ ' 作用是注释后面的语句(其实在Mysql中注释用的是'-- ',最后面有一个空格),这时整条查询语句就是
select * from table_name where id = '1' or 1=1 --+ LIMIT 0,1
其中 ' or 1=1'这条语句是永真语句,那么整条语句的查询结果是查询id=1的数据,并且因为注释掉了后面的 'LIMIT 0,1',返回的不只是一条结果,但是网页中只显示一条,所以我们只能看到一条结果。(这句话的意思是,数据库返回了多条结果给服务器,但是服务器只从中选择了一条结果显示给用户)
所以这时,我们就想查看多条结果,那么怎么办呢?
首先,我们使用order by n来获取查询语句中一共查询了多少列,就是 select 中的是多少列
从n=1,2,3...一直尝试到页面出现报错提示
对比上下两张图,可以说明一共有3列数据,则完善查询语句有
select 1, 2, 3 from table_name where id = 'x'
接下来我们想知道哪一列数据显示在网页的哪一个位置,我们可以通过union查询来构造语句
1'and 1=2 union select 1,2,3 --+
解释一下为什么要这样构造语句,首先,我们把输入的拼接到整个查询语句中
select 1,2,3 from table_name where id = '1' and 1=2 union select 1,2,3 --+ LIMIT 0,1
其中union select 是把前后两个select 语句查询的结构拼接在一起,从前面的order by 查询结果可以知道一共查询了3列数据,因此后面的union select 也要查询3列数据,不然数据库会报错.
接着我们看前面的 id='1' and 1=2,因为and需要前后都是真的时候才能返回结果,否则返回的是空结果,而 1=2永远都是假,所以前面的select查询是没有结果的,而后面的union select查询的结果是显示 1,2,3.因此在页面上我们可以看到2和3显示出来,而不是之前id=1时用户的名字和密码。
为什么要让前面的查询结果是空呢?因为我们前面有提到过,服务器返回给我们用户的只有一条结果,而为了让这条结果使我们预期的结果,也就是1,2,3. 那么我们让前面查询结果为空时,返回我们想要的结果,这时我们就能判断查询的结果分别显示在什么位置。当然我们也可以用 id=-1来使得前面的查询结果为空.
接下来,我们就可以根据上一篇文章总结的流程:数据库-数据表-列-数据 一层一层进行注入获取到我们想要的数据
1. 获取数据库,构造语句
-1' union select 1, group_concat(schema_name),3 from information_schema.schemata --+
可以看到这时,我们把服务器上所有的数据库名都列出来了。方法就是查询information_schema这个数据库的schemata表中的schema_name这个字段的数据
2. 获取数据表,构造语句
-1' union select 1, group_concat(table_name),3 from information_schema.tables where table_schema='security' --+
这条语句是查询'security'这个数据库的所有数据表,同样是通过information_shcema这个数据库,不同的是通过tables这个表
3. 获取数据列,构造语句
-1' union select 1,group(column_name),3 from information_schema.columns where table_name='users' --+
4. 获取数据
-1' union select 1,username,password from security.users where id=1 --+
通过这条语句的查询结果,我们可以猜测到原始的查询语句应该是
select username, password from users where id='x'
其中x是我们输入的参数
这时我们去翻看网页的源码可以看到和我们猜测的一样。
Less2 - Error Based - Intiger based
第二关是关于整数型数据的注入,和第一关类似,但是有一点小区别
可以看到区别在于对参数的使用上少了两个单引号 ' ',也就是查询的语句变成了
select * from table_name where id = x LIMIT 0,1
可以看到在后面输入的参数x处没有单引号包围着,所以此时我们也就不需要破坏原来的单引号,可以直接用union select。
翻看网页的源码检查一下
其他的和第一关都是一样的,我们可以利用第一关的方法和流程,同样对这关进行Sql注入的练习
Less3 - Error Based - Single quotes with twist - string
这一关和第一关一样含有单引号,另外还用了括号把参数包围了起来
当我们输入 id=1'时可以看到异常页面
可以看到报错显示了
'1'') LIMIT 0,1
结合我们前面第一关的报错,我们可以猜测到这里用到查询语句是
select * from table_name where id = (' x ') LIMIIT 0,1
这时我们要想像第一关用union select注入前,我们必须自己闭合掉左括号,然后注释右括号,也就是使用
1' ) union select 1,2,3--+
这样的语句,当我们带回到原来的语句可以看到查询语句被我们修改成
select * from table_name where id=(' 1') union select 1,2,3 --+ ') LIMIT 0,1
在 '--+'后面的语句都被注释,这样我们就能成功注入到数据库中,否则如果我们还是用第一关的
方法
' 1' union select 1,2,3 --+ '
时,查询语句就会变成
select * from table_name where id = (' 1' union select 1,2,3 --+ ') LIMIT 0,1
这时因为' --+ '注释了后面的括号,所以数据库就会报错
当然闭合这里括号不只是这一种,还有很多其他的方法,例如
') or '1'=('1'
,接下来就和第一关的类似了
Less4 - Error Based - double quotes - string
这一关是关于双引号的,而双引号和单引号是类似的,我们只需把第一关的单引号都换成双引号就可以了
当我们输入id=1"时
可以看到报错显示了
" 1 " ") LIMIT 0,1
,这意味着代码当中对id参数进行了 " "和( )的包装,翻看源码可以看到
那么我们就可以输入id=1") union select 1,2,3 --+ 进行和第一关一样的注入
总结
到目前为止,对Less1-Less4的注入学习的差不多了,基本的注入流程我们也过了一遍,按照数据库->数据表->数据列->数据的顺序一层层获取我们想要的数据。Less1到Less4是最简单的注入了,没有对用户输入的参数进行任何过滤,直接拼接到查询语句中,这使得我们能很轻松的利用sql注入进入到数据库获取到我们想要的数据.