MySQL一隐式转换

news2024/11/26 12:31:54

  我相信90%以上的同学们在平时开发时,或多或少都被隐式转换(CONVERT_IMPLICIT)坑过,甚至测出bug前你都浑然不知。你还别不信,“无形之刃,最为致命!”

 

mysql> SELECT * from t_user;
+----+-----------+----------+
| id | username  | password |
+----+-----------+----------+
|  1 | 陈哈哈    | abcd1234 |
|  2 | 侨布斯    | 1234     |
|  3 | 提莫      | 1234abcd |
+----+-----------+----------+
3 rows in set (0.00 sec)

不能展示真实数据,见谅~~ 上面是这张用户表的原始数据,侨总用下面的SQL查询自己这行数据,大家先看看有没有问题?

SELECT * from t_user where `password`=1234;
感觉没有明显的毛病?来看看结果:
mysql> SELECT * from t_user where `password`=1234;
+----+-----------+----------+
| id | username  | password |
+----+-----------+----------+
|  2 | 侨布斯    | 1234     |
|  3 | 提莫      | 1234abcd |
+----+-----------+----------+
2 rows in set, 1 warning (0.00 sec)

???这怎么把提莫队长给打现行了?

好了,其实这算是MySQL给开发者留下的不友好的礼物(坑)。今天我们一起从以下三个角度去聊一聊MySQL的隐式转换。

索引

1、SQL语句中隐式转换的坑

先看一下官方的隐试转换说明:
在这里插入图片描述

翻译成人话:

  1. 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换。
  2. 两个参数都是字符串,会按照字符串来比较,不做类型转换
  3. 两个参数都是整数,按照整数来比较,不做类型转换
  4. 十六进制的值和非数字做比较时,会被当做二进制串
  5. 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp
  6. 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较
  7. 所有其他情况下,两个参数都会被转换为浮点数再进行比较。(这里所说的浮点数一般默认为double类型)

  可以看到,非前六种以外的类型转换都要转成浮点类型来处理,这意味着什么?意味着MySQL承认了隐式转换这个事儿,还表示不爱看官方文档的哥们儿出问题活该~~

  我们用一些具体示例来看一下,通过下述SQL可见,当1234没有引号也就是整数时,‘1234abcd’ = 1234 → true,说明MySQL对’1234abcd’做了转型,转成了浮点类型,结果是:1234abcd => 1234

# 0:false;1:true
mysql> SELECT '1234abcd' = '1234';
+---------------------+
| '1234abcd' = '1234' |
+---------------------+
|                   0 |
+---------------------+
1 row in set (0.00 sec)

# 0:false;1:true
mysql> SELECT '1234abcd' = 1234;
+-------------------+
| '1234abcd' = 1234 |
+-------------------+
|                 1 |
+-------------------+
1 row in set, 1 warning (0.00 sec)

  为啥1234abcd => 1234呢? 其实’1234’和’abcd’都会转成浮点数,即:1234+0=1234,非数字类型的都被直接转成了 0

mysql> SELECT '1234' + 'abcd';
+-----------------+
| '1234' + 'abcd' |
+-----------------+
|            1234 |
+-----------------+
1 row in set, 1 warning (0.00 sec)

  你发现了什么?原来字符串涉及到 +=-/ 等等运算符时都会进行隐式转型,也就是转成double,那么字符串转double是怎么转的呢?

# 转成:'1aaaa' = 1
mysql> SELECT '1aaaa' = 1;
+-------------+
| '1aaaa' = 1 |
+-------------+
|           1 |
+-------------+
1 row in set, 1 warning (0.00 sec)

# 转成:'a1111' = 0
mysql> SELECT 'a1111' = 1;
+-------------+
| 'a1111' = 1 |
+-------------+
|           0 |
+-------------+
1 row in set, 1 warning (0.00 sec)

# 转成:0 + 0 =0
mysql> SELECT 'aa' + 'aa' = 1;
+-----------------+
| 'aa' + 'aa' = 1 |
+-----------------+
|               0 |
+-----------------+
1 row in set, 2 warnings (0.00 sec)

# 转成:0 + 0 + 1 =1
mysql> SELECT 'aa' + 'aa' + '1' = 1;
+-----------------------+
| 'aa' + 'aa' + '1' = 1 |
+-----------------------+
|                     1 |
+-----------------------+
1 row in set, 2 warnings (0.00 sec)

  可见,是以字符串从左向右取值的,且从非数字起后面的值都被转成 0,如a11111,第一位为a,则整体转为 01aaaa第一位为1,第二位为a,从第二位往后转成0,得a11111 → 0

mysql> SELECT * from t_user where `password`=1234;
+----+-----------+----------+
| id | username  | password |
+----+-----------+----------+
|  2 | 侨布斯    | 1234     |
|  3 | 提莫      | 1234abcd |
+----+-----------+----------+
2 rows in set, 1 warning (0.00 sec)

  现在我们就明白为什么能匹配到提莫了。因为在不同类型转换时"1234abcd"被转成了浮点类型,"abcd"转成浮点型后为0,因此MySQL判为:“1234abcd” = ‘1234’ + 0 。

2、黑客同学喜欢用隐式转换进行SQL注入攻击

通过第一部分隐式转换的了解,我们可以预测一些简单SQL注入的方式:

mysql> SELECT * from t_user where username='陈哈哈' and `password`=0;
+----+-----------+----------+
| id | username  | password |
+----+-----------+----------+
|  1 | 陈哈哈    | abcd1234 |
+----+-----------+----------+
1 row in set, 1 warning (0.00 sec)
果然,我账号的密码被毫无意外的攻破了

如果有些朋友公司的网站用的是下面的写法:

select * from t_user where username=${username} and `password`=${password};

  不然有些小伙伴友好的把请求参数构建成 username → a' OR 1='1 ,那么password是啥都无所谓了,是吧。

懂我意思吧,快改了。

  当然,其实很多注入攻击的真实目的,并不是用来破解用户账号的,而是破坏服务器。一般我们在页面F12发现有问题的接口后,通过脚本模拟请求参数(构造注入参数),去不断尝试自定义构造limit、order、where等条件,或许花不了多久就能通过一个不规范的请求入口,检索出该表甚至其他大表全量信息。导致公司服务器负载异常,连接数打满,CPU200%等有趣的情况。有兴趣的同学可以花几小时尝试破解自己公司的web~~

3、索引中隐式转换的坑

  同理,在MySQL根据索引进行查询时,如果你的username字段有索引且为varchar类型,且查询如下时:

select * from t_user where username=123;

该SQL会出现两个问题:

1、索引失效
  无法使用到索引查询,因为mysql会在引擎层进行类型隐式转换(CONVERT_IMPLICIT),会先把username隐式转换成浮点数,然后再跟你的123进行比较,然而你的索引是建在username上的,并不是在转换后的username上的,所以进行转换后的username相当于没有索引。会全表扫描,换做大表中,无法使用索引,你懂得。

2、查询结果不准确
  第一部分我们已经举例说明,MySQL在隐式转换时的varchar转double,会出现很多意想不到的情况,比如 “123”," 123","123a"都会转成123,实际场景中都是不允许出现的。

 

总结

就是当sql中一个字符串和一个数字做+=-/ 计算时,如"a1bc"+1,   "ccccd3"=0

这个字符串中的非数字的字符会被隐式转换成0并且再转换为空,再去做比较.只分以下两种情况:

1.前面的字符不是数字时,直接等于0,如"a1"=0,"abcd1"=0

2.前面的字符是数字时,从第一个开始截取,从左往右直到出现的第一个不是数字的字符为止,截取的字符串就是最终转换的值,如"1a"=1,"2a3b"=2,"55555h666666"=55555

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/364967.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode】剑指 Offer 11. 旋转数组的最小数字 p82 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/ 1. 题目介绍&#xff08;11. 旋转数组的最小数字&#xff09; 把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;我们称之为数组的旋转。 给你一个可能存在 重复 元素值…

关于微前端,你想知道的都在这!

更多请关注微前端专题 https://codeteenager.github.io/Micro-Frontends/ 介绍 微前端官网&#xff1a;https://micro-frontends.org/ 问题&#xff1a;如何实现多个应用之间的资源共享&#xff1f; 之前比较多的处理方式是npm包形式抽离和引用&#xff0c;比如多个应用项目之…

浅谈Redisson实现分布式锁的原理

1.Redisson简介 Redis 是最流行的 NoSQL 数据库解决方案之一&#xff0c;而 Java 是世界上最流行&#xff08;注意&#xff0c;我没有说“最好”&#xff09;的编程语言之一。虽然两者看起来很自然地在一起“工作”&#xff0c;但是要知道&#xff0c;Redis 其实并没有对 Java…

windows共享文件夹(目录)(SMB服务)

SMB服务&#xff0c;文件共享服务&#xff0c;俗称文件夹&#xff08;目录&#xff09;、打印机等共享 一、创建共享用户 windos系统中&#xff0c;文件夹共享需要设置指定用户与密码&#xff0c;通过输入用户和密码进行连接&#xff0c;在设置共享时系统中有Everyone所有人设…

【Linux学习笔记】1.Linux 简介及安装

前言 本章介绍Linux及其安装方法。 Linux 简介 Linux 内核最初只是由芬兰人林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;在赫尔辛基大学上学时出于个人爱好而编写的。 Linux 是一套免费使用和自由传播的类 Unix 操作系统&#xff0c;是一个基于 POSIX 和 UNIX 的多…

【基础语法】JavaScript 全栈体系(四)

JavaScript 基础 第五章 类型转换 一、为什么需要类型转换&#xff1f; JavaScript是弱数据类型&#xff1a; JavaScript也不知道变量到底属于那种数据类型&#xff0c;只有赋值了才清楚。 坑&#xff1a; 使用表单、prompt 获取过来的数据默认是字符串类型的&#xff0c;此…

JVM及其内存模型

目录儿一、JVM1.1 为什么需要JVM&#xff1f;1.2 JVM内存模型1.3 堆&#xff08;Heap&#xff09;1.4 方法区&#xff08;Method Area&#xff09;1.5 虚拟机栈(JVM Stack)1.6 本地方法栈(Native Stack)1.7 程序计数器&#xff08;PC Register&#xff09;一、JVM JVM是Java V…

I-Cache 和 D-Cache

定义ICache和DCache是一种内存&#xff0c;虽然目前接触了好几种内存&#xff0c;寄存器&#xff0c;DDR等&#xff0c;它们在物理上的工作原理虽然不同&#xff0c;但是访问属性却很像。在速度上CPU > 寄存器 > Cache > SRAM &#xff1e;&#xff30;&#xff33;&…

100种思维模型之六顶帽思维模型-018

工作中&#xff0c;经常开会&#xff0c;开会于工作当然无可厚非。 可是&#xff0c;现实中的会议&#xff0c;往往存在效率低&#xff0c;效果不佳的问题。如&#xff0c;连续开一天的研究讨论会&#xff0c;最后没能讨论出个所以然&#xff0c;又或者会议有了决策&#xff0c…

QT_dbus(ipc进程间通讯)

QT_dbus(ipc进程间通讯) 前言&#xff1a; 参考链接&#xff1a; https://www.cnblogs.com/brt3/p/9614899.html https://blog.csdn.net/weixin_43246170/article/details/120994311 https://blog.csdn.net/kchmmd/article/details/118605315 一个大型项目可能需要多个子程序同…

《计算机网络:自顶向下方法》实验5:ARP协议分析 Wireshark实验

实验13:ARP协议分析 1 What is the 48-bit Ethernet address of your computer? 00:d0:59:a9:3d:68 2 What is the 48-bit destination address in the Ethernet frame? Is this the Ethernet address of gaia.cs.umass.edu? (Hint: the answer is no). What device has …

推荐算法—widedeep原理知识总结代码实现

wide&deep原理知识总结代码实现1. Wide&Deep 模型的结构1.1 模型的记忆能力1.2 模型的泛化能力2. Wide&Deep 模型的应用场景3. Wide&Deep 模型的代码实现3.1 tensorflow实现3.2 pytorch实现今天&#xff0c;总结一个在业界有着巨大影响力的推荐模型&#xff0c…

设计模式.工厂模式.黑马跟学笔记

设计模式.工厂模式4.创建型模式4.2 工厂模式4.2.1 概述4.2.2 简单工厂模式4.2.2.1 结构4.2.2.2 实现4.2.2.4 优缺点4.2.2.3 扩展4.2.3 工厂方法模式4.2.3.1 概念4.2.3.2 结构4.2.3.3 实现4.2.3.4 优缺点4.2.4 抽象工厂模式4.2.4.1 概念4.2.4.2 结构4.2.4.2 实现4.2.4.3 优缺点4…

C语言进阶(六)—— 结构体

1. 结构体基础知识1.1 结构体类型的定义struct Person{char name[64];int age; };typedef struct _PERSON{char name[64];int age; }Person;注意&#xff1a;定义结构体类型时不要直接给成员赋值&#xff0c;结构体只是一个类型&#xff0c;编译器还没有为其分配空间&#xff0…

【Kubernetes 入门实战课】Day02——初识容器

系列文章目录 【Kubernetes 入门实战课】Day01——搭建kubernetes实验环境(一) 文章目录系列文章目录前言一、Docker的诞生二、Docker的形态1、Docker Desktop2、Docker Engine二、Docker的安装1、服务器连接外网安装2、服务器不通外网三、Docker的使用三、Docker的架构总结前…

JavaWeb11-死锁

目录 1.死锁定义 1.1.代码演示 1.2.使用jconsole/jvisualvm/jmc查看死锁 ①使用jconsole&#xff1a;最简单。 ②使用jvisualvm&#xff1a;&#xff08;Java虚拟机&#xff09;更方便&#xff0c;更直观&#xff0c;更智能&#xff0c;更高级&#xff0c;是合适的选择。 …

Melis4.0[D1s]:2.启动流程(GUI桌面加载部分)跟踪笔记

文章目录0. 控制台输出信息等级设置0.1 设置log level 4 无法正常启动1.宏观启动流程1.1 控制台入口函数finsh_thread_entry()执行《startup.sh》1.2 《startup.sh》启动桌面GUI模块1.2.1 《startup.sh》加载 desktop.mod1.2.2 desktop.mod加载 init.axf1.2.3 init.axf 介绍1.…

C#与三菱PLC MC协议通信,Java与三菱PLC MC协议通信

三菱PLC的MC协议是一种常用的通信协议&#xff0c;用于实现三菱PLC与其他设备之间的通信。以下是一些关于MC协议的基本信息&#xff1a;协议格式MC协议的通信数据格式如下&#xff1a;数据头网络编号PC编号目标模块IO编号目标模块站号本机模块IO编号本机模块站号请求数据长度请…

Linud SSH与SCP的配置

目录 配置SSH协议 配置服务器通过密钥进行认证 配置SCP完成文件传输 ssh协议讲解 SSH协议理论讲解_静下心来敲木鱼的博客-CSDN博客https://blog.csdn.net/m0_49864110/article/details/128500490?ops_request_misc%257B%2522request%255Fid%2522%253A%2522167704203816800…

不加大资金投入,仅凭智能名片如何解决企业营销难题的?

中国90%以上的中小企业想要竞争和发展&#xff0c;就必须推广自己的品牌&#xff0c;提高自己的知名度。在小程序之前&#xff0c;APP是主流&#xff0c;但大多数中小企业负担不起APP的开发和昂贵的营销成本。 进入微信互联网时代后&#xff0c;为了帮助企业以更低的成本获得…