MySQL报错注入之Xpath报错&floor函数报错
前言
报错注入的使用场景一般是页面无法正常回显数据库查询的内容,但是会详细显示查询过程的错误信息。如果连错误信息都没有,那就是盲注了。报错注入的原理就是将子查询语句查询到的内容和错误信息一同带出来。
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)被计算多次导致的。
还原一下具体的查询过程:
- 查询前默认会建立空虚拟表如下图:

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

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

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

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

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

- 查询虚表,发现键值没有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函数报错的更多相关文章
- MySQL报错注入总结
mysql暴错注入方法整理,通过floor,UpdateXml,ExtractValue,NAME_CONST,Error based Double Query Injection等方法. 报错注入: ...
- ctfhub 报错注入
payload 1 Union select count(*),concat((查询语句),0x26,floor(rand(0)*2))x from information_schema.colu ...
- sql注入--双查询报错注入
sql注入--双查询报错注入 背景:在sqli-labs第五关时,即使sql语句构造成功页面也没有回显出我们需要的信息,看到了有使用双查询操作造成报错的方式获得数据库信息,于是研究了一下双查询的报错原 ...
- SQL注入——报错注入
0x00 背景 SQL注入长期位于OWASP TOP10 榜首,对Web 安全有着很大的影响,黑客们往往在注入过程中根据错误回显进行判断,但是现在非常多的Web程序没有正常的错误回显,这样就需要我们利 ...
- sql注入 报错注入常用的三种函数
1.floor()函数 报错原因是 报错的原因是因为rand()函数在查询的时候会执行一次,插入的时候还会执行一次.这就是整个语句报错的关键 前面说过floor(rand(0)*2) 前六位是0110 ...
- ctfhub技能树—sql注入—报错注入
打开靶机 payload 1 Union select count(*),concat((查询语句),0x26,floor(rand(0)*2))x from information_schema.c ...
- MySQL 常用报错注入原理分析
简介 这段时间学习SQL盲注中的报错注入,发现语句就是那么两句,但是一直不知道报错原因,所以看着别人的帖子学习一番,小本本记下来 (1) count() , rand() , group by 1.报 ...
- MySQL暴错注入方法
mysql暴错注入方法整理,通过floor,UpdateXml,ExtractValue,NAME_CONST,Error based Double Query Injection等方法 1.通过fl ...
- MySQL报错注入函数汇总及常用注入语句
版权声明:本文转载自网络内容,下面附原创链接原创链接:https://blog.csdn.net/Auuuuuuuu/article/details/91415165 常用函数 字符串连接函数,将多个 ...
- SQL注入之Mysql报错注入
--志向和热爱是伟大行为的双翼. 昨天偷懒了没学什么东西,先自我反省一下 - -. 今天认真的学习了一下Mysql报错注入利用方法及原理,好久之前就像认真的学一下这个了,是在上海市大学生网络安全大赛中 ...
随机推荐
- Ubuntu 安装基于 DEB 的 Firefox
自从 Canonical 推出了 Snap 之后,在所有新推出的 Ubuntu 发行版中都预装了 Snap 版的 Firefox,并将 APT 中的 Firefox 包指向了 Snap 的 Firef ...
- 解密华为问界M7 Pro:智能出行的全新里程碑与技术亮点
解读华为问界M7 Pro的智能里程碑 引言 2024年8月,智能出行领域迎来了一个激动人心的时刻--问界M7 Pro的重磅发布.这款智能SUV,不仅是华为在汽车领域的又一次大胆尝试,更是鸿蒙智行系统的 ...
- Python新手爬虫四:爬取视频
老样子,先上最后成功源码(在D盘下创建'好看视频'文件夹,直接运行即可获取视频): import sys import re,os import requests from you_get impor ...
- 【YashanDB知识库】YashanDB 开机自启
[问题分类] YashanDB 开机自启 [关键字] 开机自启,依赖包 [问题描述] 数据库所在服务器重启后只拉起monit.yasom.yasom进程,缺少yasdb进程: [问题原因分析] 数据库 ...
- 光影精灵10 Win1+Ubuntu18.04 双系统 踩坑记录
前言 第二年准备报名智能车了,当然还是创意组别.刚好买了今年新出的电脑光影精灵10,我想着也给它安一个双系统.但是没想到,相比于之前那个老电脑,新电脑的新硬件和驱动问题远比老电脑麻烦的多. 在经历了一 ...
- SQL Server 中的 NUL 设备/NIL设备
SQL Server 中的 NUL 设备/NIL设备 在 SQL Server 中,有一个特殊的设备叫做 NUL(注意,不是 NULL),它类似于文件系统中的"黑洞".NUL 设备 ...
- Nuxt.js 应用中的 app:mounted 钩子详解
title: Nuxt.js 应用中的 app:mounted 钩子详解 date: 2024/10/5 updated: 2024/10/5 author: cmdragon excerpt: ap ...
- JVM--解析运行期优化与JIT编译器
JVM开发团队一直在努力,缩小Java与C/C++语言在运行效率上的差距. 本篇博客,我们来谈一谈JVM(HotSpot)为了提高Java程序的运行效率,都实现了哪些激动人心的技术- 1 JIT编译器 ...
- threejs 几何体的本质 顶点
几何体的线框模式, 一个正方平面最少可以由4个顶点组成,两个三角形组成(公用了 2个顶点,使用了索引创建顶点属性) . // 导入 threejs import * as THREE from &qu ...
- 动态去读 dll 文件
// 反射动态读取 dll // Assembly assembly = Assembly.LoadFile(); 路径 // Assembly assembly = Assembly.LoadFro ...