特别申明
本文章仅供学习使用,其余利用本文章内容进行的任何行为与本人无关!做任何渗透操作前,请一定三思,做个遵纪守法的好公民!
简介
在初见SQL注入提到三种分类方式,其中一个是根据注入是否有回显来进行分类,本文将详细讲解有回显这类的注入方式。有有回显的注入,顾名思义,程序会将后端执行SQL查询语句的结果,返回显到页面中,通过各种巧妙的方式让各种你想要知道的关键信息显示在页面中。有回显的注入常见的有联合注入和报错注入,本文将详细讲解union联合注入。
正文
一、概念
个人理解联合注入是根据一次次的试探结果,确定表、库、字段名等,最后结合sql语句中union操作符的特性,获取到你想要的数据。说到联合注入,这里提前跟大家介绍下SQL中“union”和“order by”,方便理解后文的操作步骤。
二、利用条件
1、注入页面有回显;
2、允许使用order by;
3、允许使用union;
三、union
用于合并两个或多个 SELECT 语句的结果集。等同于将一个表追加到另一个表,从而实现将两个表的查询组合到一起,使用谓词为UNION或UNION ALL。要注意的是UNION 内部的 SELECT 语句必须拥有相同数量的列,列也必须拥有相似的数据类型,每条 SELECT 语句中的列的顺序必须相同。例如下面的语句,
SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2
四、order by
用于对结果集按照一个列或者多个列进行排序,默认按照升序对内容进行排序。
order by带列名进行排序,如对model列排序:
select * from django_content_type order by model;
order by带第几列进行排序,如对第二列排序:
select * from django_content_type order by 2;
这个时候有意思的事情来了,那么如果我输入的列数不存在呢?当然是报错啦,如下图,我输入不存在的第4列,得到的返回如下:
根据这个情况,我们就可以得出一个结论,假设我order by后面带的参数为n
1、如果返回正常,则这个表里的列数大于n;
2、如果报错,则这个表里的列数小于n;
根据上面这个结论,可以用二分法判断出这个表的列数。
五、注入步骤
1、判断注入点
2、判断注入点为整型还是字符型
3、使用order by推断字段数,即表中列的数量
4、使用union,确认显示位,即会显示的字段
5、获取数据库名
6、获取数据库表名
7、获取数据库表中所有字段
8、获取字段中数据
这里我结合dvwa模拟每一步的操作
1、判断注入点
首先打开页面查看注入点显然是这个输入框
2、判断注入点为整型还是字符型
首先分别输入1' and '1'='1和1' and '1'='2,观察两个返回结果是否相同,如果相同,则为字符型,如果不同,则为整型,可以看到结果如下,显然返回结果不同,那么可以确定注入点为整型;
3、使用order by推断字段数,即表中列的数量
在注入点输入1' order by 5#,返回错误,如下图,那么显然字段列数小于5;
(url中的%27代表“' ”字符,%23代表“#”字符)
接着尝试输入1' order by 2#,结果正常输出,可以确定只有2列字段;
4、使用union,确认显示位,即会显示的字段
构造输入方式,保证输入的字符能正确拼接在本来的sql中,在注入点输入1' union select 1,2 #,上一步已经判断此sql中只有两列,所以select后面只能输入两列;最后的“#”字符的目的是注释掉后面本来的sql语句。可以看到返回如下图,能正常显示;
5、获取数据库名
在注入点输入1' union select 1,2 #,返回如下图,获取数据库用户名及数据库名dvwa,;
6、获取数据库表名
在注入点输入下面语句,获取所有表名
1' union select group_concat(table_name),database() from information_schema.tables where table_schema = database() #
7、获取数据库表中所有字段
1' union select group_concat(column_name),database() from information_schema.columns where table_schema = database() #
8、获取字段中数据
只要修改sql语句,就能获取字段中的数据了,具体的这里就不展示了,现实中,到这一步你应该立刻,马上停止操作,然后同厂商同步此漏洞!切记,要做一个遵纪守法的好公民!