sql注入学习笔记3
基于报错注入
https://www.jianshu.com/p/8c2343705100 简书的一篇文章,我结合了这个还有sqli-labs以及一些其他文章和自己拿自己的数据库进行的实验总结了点自己的理解
union select 1,count(*),concat(0x3a,0x3a,(user()),0x3a,0x3a,floor(rand()*2))a from information_schema.columns group by a--+
这个语句有几个点,a是concat(0x3a,0x3a,(user()),0x3a,0x3a,floor(rand()*2))的别名,不需要AS,测试了下用AS是一样的效果。
FLOOR(x) |
返回小于或等于x的最大整数 SELECT FLOOR(1.5) -- 返回1 |
RAND() |
返回0->1的随机数 SELECT RAND() --0.93099315644334 |
RAND(x) |
返回0->1的随机数,x值相同时返回的随机数相同 SELECT RAND(2) --1.5865798029924 |
这个值没什么意义,只是floor(rand()*2)或floor(rand(0)*2)将会随机返回0或1
但他们还是有区别的,带0参数的是有规律可以寻的,前面都是011011,不管试几次都是这样,而不带参数的,只要重试一次就会不一样,且无规律
以下是看别人的解释,侵删
union select 1,count(*),concat(0x3a,0x3a,(user()),0x3a,0x3a,floor(rand()*2))a from information_schema.columns group by a--+
- 查询前默认会建立空虚拟表。
2.取第一条记录,执行floor(rand(0)*2),发现结果为0(第一次计算),查询虚拟表,发现0的键值不存在,则floor(rand(0)*2)会被再计算一次,结果为1(第二次计算),插入虚表,这时第一条记录
3.查询第二条记录,再次计算floor(rand(0)*2),发现结果为1(第三次计算),查询虚表,发现1的键值存在,所以floor(rand(0)*2)不会被计算第二次,直接count(*)加1,第二条记录查询完毕查询完毕
4.查询第三条记录,再次计算floor(rand(0)*2),发现结果为0(第4次计算),查询虚表,发现键值没有0,则数据库尝试插入一条新的数据,在插入数据时floor(rand(0)*2)被再次计算,作为虚表的主键,其值为1(第5次计算),然而1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以插入的时候就直接报错了
整个查询过程floor(rand(0)*2)被计算了5次,查询原数据表3次,所以这就是为什么数据表中需要3条数据,使用该语句才会报错的原因。
而floor(rand()*2)不确定,所以有时会报错,有时不会,多刷新几次就看得出来
数值类型超出范围进行报错注入
这里用到的是exp函数,其它的也有许多存在这个注入
可以看到当exp中参数超过709就会报错
union select (exp(~(select * FROM(SELECT USER())a))),2,3--+
解释下当exp里面的函数成功执行就会返回0,~0表示将0按位取反,0按位得到’18446744073709551615’明显大于709,将会报错
应该注意的是这里的a必须要有,也就是必须要给子查询一个别名,否则会报这样的错误:
Every derived table must have its own alias
这句话的意思是说每个派生出来的表都必须有一个自己的别名
一般在多表查询时,会出现此错误。
因为,进行嵌套查询的时候子查询出来的的结果是作为一个派生表来进行上一级的查询的,所以子查询的结果必须要有一个别名
利用bigint溢出进行报错注入
数据类型BIGINT的长度为8字节
有符号最大数为’9223372036854775807’,无符号最大数为’18446744073709551615’
union select (!(select * from (select user())x) - ~0),2,3--+
也可以用+,不过+会被浏览器解析为空白字符,当然也可以用%2B替换+