前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL 空格问题

MySQL 空格问题

作者头像
Yifans_Z
发布2023-08-23 18:46:03
3040
发布2023-08-23 18:46:03
举报
文章被收录于专栏:与荔枝一起成长

看现象

创建一个测试数据库表,插入测试数据:

代码语言:javascript
复制
CREATE TABLE `blank_space` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `uid` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
  `desc` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uniq_key` (`uid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `blank_space`(`id`, `uid`, `desc`) VALUES (1, 'abc ', '末尾1个');
INSERT INTO `blank_space`(`id`, `uid`, `desc`) VALUES (2, ' abc', '开头1个');
INSERT INTO `blank_space`(`id`, `uid`, `desc`) VALUES (3, '  abc', '开头2个');

id

uid

desc

1

abc_

末尾 1 个

2

_abc

开头 1 个

3

__abc

开头 2 个

uid 实际上没有 _,这样写是为了看到空格。

执行操作:

代码语言:javascript
复制
SELECT * FROM blank_space WHERE uid = 'abc';

SELECT * FROM blank_space WHERE uid = 'abc ';

SELECT * FROM blank_space WHERE uid = 'abc   ';

都可以查询出:

id

uid

desc

1

abc_

末尾 1 个

执行操作:

代码语言:javascript
复制
INSERT INTO `blank_space`(`uid`, `desc`) VALUES ('abc', '无空格');
-- 1062 - Duplicate entry 'abc' for key 'uniq_key', Time: 0.322000s

INSERT INTO `blank_space`(`uid`, `desc`) VALUES ('abc  ', '末位两个');
-- 1062 - Duplicate entry 'abc' for key 'uniq_key', Time: 0.322000s

原因

MySQL 校对规则属于 PADSPACE,会忽略尾部空格。针对的是 varchar char text 等文本类的数据类型。此为 SQL 标准化行为。无需要设置也无法改变。

解决方案

代码语言:javascript
复制
SELECT * FROM blank_space WHERE uid = BINARY 'abc';
-- 0 records

SELECT * FROM blank_space WHERE uid = BINARY 'abc ';
-- 1 records

SELECT * FROM blank_space WHERE uid = BINARY 'abc   ';
-- 0 records


SELECT * FROM blank_space WHERE uid like 'abc';
-- 0 records

SELECT * FROM blank_space WHERE uid like 'abc ';
-- 1 records

SELECT * FROM blank_space WHERE uid like 'abc   ';
-- 0 records

BINARY 不是函数,是类型转换运算符,它用来强制它后面的字符串为一个二进制字符串,可以理解成精确匹配。

约束攻击

需要在非严格模式下。

代码语言:javascript
复制
SET sql_mode = '';

CREATE TABLE `blank_space_attack` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `uid` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
  `pwd` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `blank_space_attack`(`id`, `uid`, `pwd`) VALUES (1, 'admin', '123');
INSERT INTO `blank_space_attack`(`id`, `uid`, `pwd`) VALUES (2, 'tim', '234');

攻击:

代码语言:javascript
复制
INSERT INTO `blank_space_attack`(`uid`, `pwd`) VALUES ('admin      1', 'easy');

结果:

代码语言:javascript
复制

select * from blank_space_attack where uid = "admin" and pwd = "easy";

id

uid

desc

3

admin_____

easy

限制条件

  • 服务端没有对用户名长度进行限制。如果服务端限制了用户名长度就不能导致数据库截断,也就没有利用条件。
  • 登陆验证的 SQL 语句必须是用户名和密码一起验证。如果是验证流程是先根据用户名查找出对应的密码,然后再比对密码的话,那么也不能进行利用。因为当使用 admin 为用户名来查询密码的话,数据库此时就会返回两条记录,而一般取第一条则是目标用户的记录,那么你传输的密码肯定是和目标用户密码匹配不上的。
  • 验证成功后返回的必须是用户传递进来的用户名,而不是从数据库取出的用户名。因为当我们以用户 admin 和密码 easy 登陆时,其实数据库返回的是我们自己的用户信息,而我们的用户名其实是 admin_____,如果此后的业务逻辑以该用户名为准,那么就不能达到越权的目的了。

References

– EOF –

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 看现象
  • 原因
  • 解决方案
  • 约束攻击
    • 限制条件
    • References
    相关产品与服务
    云数据库 MySQL
    腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档