最基础sqli-labs平台sql注入语法讲解
文章目录
-
- 最基础sqli-labs平台sql注入语法讲解
-
- 一、sql注入的简单介绍
- 二、sqli-labs平台的搭建
- 二、实验
-
- 1.Less-1(single quotes)
- 2.Less-2(intiger based)
- 3.Less-3(single quotes with twist)
- 4.Less-4(double quotes)
- 5.Less-5(double injection-single quotes)
- 6.Less-6(double injection-double quotes)
- 7.Less-7(dump into outfile)
- 8.Less-8(blind-boolian based-single quotes)
- 9.Less-9(blind-time based-single quotes)
- 10.Less-10(blind-time based-double quotes)
最近也是沉迷于学习sql注入,越是了解越是发现其中的奥妙与乐趣,在这篇文章中主要是以sqli-labs平台的前十关为例子,记录一些sql注入方面的基础知识,方便以后sql注入的深入学习。
一、sql注入的简单介绍
sql注入就是指web应用程序对用户输入数据的合法性没有判断,前端传入后端的参数是攻击者可控的,而且参数带入数据库查询,攻击者可以通过构造不同的sql语句来实现对数据库的任意操作。也就是说,只要满足两个条件,即可以判段存在sql注入漏洞:
1.参数用户可控:前端传给后端的参数内容是用户可以控制的。
2.参数带入数据库查询:传入的参数拼接到sql语句中,且带入数据库查询。
通白一点讲,就是我们自己构造的sql语句中,参数对于数据库是有意义的,可以收到响应的。
下面的一些内容需要我们记住:
1.在mysql5.0版本后,mysql数据库中存放着一个“information_schema”的数据库,在该库中有三个表,分别是SCHEMATA、TABLES和COLUMNS。
-
schemata表存放着该用户创建的所有数据库的库名,在该表中记录数据库库名的字段名为schema_name,如图:
-
tables表中存放着用户创建的所有数据库的库名和表名,记录数据库库名和表名的字段名分别为table_schema和table_name,如图:
-
columns表中存放着用户创建的所有数据库的库名,表名和字段名,而该表中记录数据库库名、表名和字段名的字段名分别为table_schema、table_name和column_name,如图:
2.几个函数的作用需要记住:
- database():返回当前网站使用的数据库库名。
- version():返回当前mysql数据库的版本。
- user():返回当前mysql的用户的用户名。
- @@version_complie_os:返回当前操作系统类型。
二、sqli-labs平台的搭建
见另一篇文章《wampserver下sql注入平台sqli-labs的搭建》
二、实验
1.Less-1(single quotes)
提示说到这是一个单引号注入,什么是单引号注入?简单的说,就是传入的参数被一对单引号包围了。
以下面这条PHP语句为例:
$query="select * from tables where id = $_get['id'];
这条语句是通过get方法获取我们写入的参数id,然后再根据参数id执行其它语句,当我们传入参数id=1时,那么这条语句的实际执行为
select * from users where id = '1';
但是当我们在id=1后加入单引号后,明显语句变为
select * from users where id = 'id'';
那么,就会因识别不了参数id而提示语法错误或语法不匹配的信息。来到sqli-labs平台看一下。
当输入?id=1时,页面显示正常
当我们加一个单引号,输入?id=1’时,页面提示在“1”处使用正确的语法
当我们在后面再加一个“–+”时,页面又恢复正常。在这里“–+”就是注释符号,将后面的单引号和其它信息注释掉了,在语句中和我们输入的单引号共同组成一对单引号,所以页面正常显示。
我们知道在mysql语句中,“#”,“–”都可以表示注释,但是在sqli-labs平台中,只有“–+”能作为注释符号直接使用,原因可以阅读文章《sql注入中的–+注释问题探索》
(好嘞,废话说完了下面开始干活了)
我们可以很明显的看到,Less-1是将数据输出到页面的,所以我们可以使用union注入的方式
执行下面这条语句,发现页面和?id=1的结果一样。
?id=1'order by 1--+
解释一下:这条语句的意思就是查询当前表中id为1的数据,并按第一字段排序。那么反过来想,当我们访问的字段不存在时,页面会报错,也就是说我们可以通过这条语句查询当前表的字段数。
再次输入语句,页面也是和?id=1的页面一样,所以存在第三字段
?id=1'order by 3--+
输入语句,显示未知字段的错误,所以得出结论,当前表存在三个字段。
?id=1'order by 4--+
知道了表中的字段数,还要知道哪些字段是可以回显到页面上的,执行下面的语句
?id=-1'union select 1,2,3--+
在这里,由于代码只返回第一条结果,即id=1的内容,所以页面上不会显示union select获取的结果,所以我们需要将前面id的值设为空或者数据库中没有的id的值,比如-1。这样就会返回union select的结果了。
可以看到,返回的结果为2和3,意味着在原语句中第二、三字段的内容可以回显到页面上,所以在union select 1,2,3中,2和3的位置可以输入sql语句。
于是可以使用下面的语句得到当前数据库是“security”
?id=-1'union select 1,2,database()--+
知道了数据库security,下面要想办法知道这个数据库下的表都有什么,可以用这条语句,可以得到emails,referers,uagents,和users这四张表:
?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
解释一下这条语句的意思:
前面提到在information_schema数据库下存在着一张tables表,表中存放着用户创建的所有数据库库名和表名,而之前知道了当前数据库为security,所以只需要在tables表中使用查询语句查询table_schema字段也就是数据库名为security的对应表名。(下面用到的语句也都大同小异)
还有一点就是用到了group_concat()这个函数,它的作用通白一点将,就是将同一列的内容连接起来并当成一个字符串返回。为什么要用到这个函数呢?因为在原语句中,只会返回第一个字符串,也就是说,如果把这个函数去掉的话,页面只会打印“emails”这个表,那么加上了这个函数后,它将这一列都当成了一个字符串返回,所以就可以看到所有的表了。
在得到的表中有一张users表,很明显可以猜测这张表中存放着我们想要得到的用户名和密码,所以我们可以使用下面的语句查询该表中的字段名
?id=-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'--+
爆出来字段名为“id”,“usename”,“password”,目的达成了!
使用下面这个语句:
?id=-1'union select 1,group_concat(username),group_concat(password) from security.users--+
2.Less-2(intiger based)
根据提示,Less-2是一个数值型注入漏洞,那么什么是数值型注入呢?可以这样理解:
原语句类似于下面这条语句,就是说参数id不再被引号所闭合
select * from users where id = $id;
当我们传入参数时,所传入的参数必须是一个数值或者是一个被引号所闭合的数值,才不会出现语法错误,例如传入?id=1或者?id=’1‘均不会报错,如果原语句是单引号注入的话,传入?id='1’会发生报错。那么应该如何有效的区分单引号注入和字符型注入呢?
- 对于单引号注入,只要我们传入的参数能使原语句中的引号形成有效的闭合,且闭合引号内的数值是有效的,就不会出现语法错误。利用这个思想可以使用下面的语句:
?id=1'and '1'='1
这条语句在原语句中的实际执行为
select * from users where id=‘1’and’1’=‘1’;
很明显并没有语法错误,因为1=1为真,而where语句中的id=1也是真,所以页面会返回和id=1相同的结果。 如果传入这个参数:
?id=1'and'1'='2
页面并没有显示任何内容,或者说显示了与id=1不同的内容,但是同样不会报错。
在经过上面两条语句测试后,如果成立,就是单引号注入。
- 对于数值型注入,我们传入的参数不应有任何的引号或者传入被引号闭合的参数,那么就不会发生语法错误,利用这个思想可以用下面两条语句测试:
?id=1 and 1=1
?id=1 and 1=2
如果满足以上两个语句的测试结果,则可以判断为数值型注入。相应的我们也可使用?id='1'and'1'='1'
和?id='1'and'1'='2'
这两条语句进行测试,效果一样。
(下面开始干活emo~)
还是使用union联合的方式进行注入实验,其实和上面单引号注入一样,只是在传入参数是不要加单引号就行了,所以可以使用下面的语句
?id=1 order by 3--+
?id=1 order by -4-+
确定还是三个字段
然后
?id=-1 union select 1,2,3--+
(还是啰嗦一句,因为数值型注入不会受到后面引号的影响,所以在这里的注释符“–+”也可以省略)
?id=-1 union select 1,2,database()--+
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()--+
?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'--+
?id=-1 union select 1,group_concat(username),group_concat(password) from users--+
3.Less-3(single quotes with twist)
根据提示这是一个被括号闭合的单引号注入,通过下面这条语句可以很清楚的理解这个注入类型。
select * from users where id =('$id')
所以说,当我们输入参数id时,既要保证单引号的闭合,还要帮助括号的闭合。
例如,当我们输入?id=1'
以及?id=1'--+
均会报错,并且在我们输入?id=1'
时页面很明显的提示在“1”)附近出现语法错误。
而当输入?id=1')--+
时,页面就不会报错。这可以作为推断该类型注入的依据。
至于实验过程,与上面两个实验的语句并无太大差别,只需要秉承引号和括号闭合的原则,即在引号后面再加一个单括号就行了。
?id=1')order by 3--+
?id=1')order by 4--+
?id=-1')union select 1,2,database()--+
?id=-1')union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()