作为计算机安全课程介绍的一部分,我们有一个关于SQL注入的简短单元.家庭作业(job)之一是一个基本的未经消毒的登录页面.预期的解决方案与classic ' or 1=1; -- 类似,但我们始终欢迎学生寻找非常规的解决方案.

One such solution was presented to me recently: inputting '--' for the password seems to perform a successful SQL injection. This would cause the query to be evaluated as something like:
SELECT * FROM users WHERE name='admin' AND password=''--'';

在这里,--'';不会被解析为 comments ,因为MariaDB要求 comments 后面有空位.事实上,如果双破折号was被解析为注释,则此查询根本不会返回任何内容;同样,我们将有password='',假设密码非空,它的计算结果为假.

结尾处额外的一对引号似乎是必要的:将其保留为password=''--;或在其后面插入其他数据(password=''--1;)会导致条件被判断为假,正如预期的那样.

一些快速测试未能在其他数据库中重现这种行为--据我所知,这是MariaDB特定的行为.The documentation确认两个没有空位的破折号不会被解析为 comments ,但没有详细说明它们被解析为什么.EDIT:不知怎的,我设法错过了一个事实:这种情况也发生在SQL中.事实上,这种行为发生在任何SQL fork(不仅仅是MariaDB)中.

--后面没有空间时会做什么?为什么它会导致比较结果为真?

玩具示例:

CREATE TABLE users (
  userid INTEGER PRIMARY KEY,
  username TEXT NOT NULL,
  password TEXT NOT NULL
);

INSERT INTO users VALUES (0001, 'admin', 'S3cur3P4ssw0rd!');
INSERT INTO users VALUES (0002, 'generic_user', 'Password');

SELECT * FROM users WHERE username='admin' AND password=''; -- empty password, query returns no users
SELECT * FROM users WHERE username='admin' AND password=''-- ''; -- parsed as comment, equivalent to above query, returns no users
SELECT * FROM users WHERE username='admin' AND password=''--''; -- query returns admin user
SELECT * FROM users WHERE username='admin' AND password=''--; -- query returns zero users
SELECT * FROM users WHERE username='admin' AND password=''--1; -- query returns zero users

推荐答案

这个特定的SQL注入使用两个方面:

首先,不带空位的--及其后面的值被解析为负值的减法.当您运行查询时

SELECT '10'--'9'

您将得到以下结果:

+-----------+
| '10'--'9' |
+-----------+
|        19 |
+-----------+

因此当您运行查询时

SELECT ''--''

得到第一个数字(0)减go 负的第二个数字(-0)的结果,结果为0.

+--------+
| ''--'' |
+--------+
|      0 |
+--------+

第二部分是,当上下文要求字符串必须是数字时,MariaDB(和SQL)try 将字符串转换为数字.请参阅以下查询:

SELECT 'some value', '42 apples';

这没有什么特别的结果:

+------------+-----------+
| some value | 42 apples |
+------------+-----------+
| some value | 42 apples |
+------------+-----------+

但当你这样做算术时

SELECT 'some value'+0, '42 apples'+0;

你会得到这个:

+----------------+---------------+
| 'some value'+0 | '42 apples'+0 |
+----------------+---------------+
|              0 |            42 |
+----------------+---------------+

这可以用上面的算术来对付您,其值为0.查询

SELECT password, ''--'', password+0, password=0, password=''--'' FROM users;

将显示以下结果(我添加了一个新用户,密码开头有一个数字):

+-----------------+--------+------------+------------+-----------------+
| password        | ''--'' | password+0 | password=0 | password=''--'' |
+-----------------+--------+------------+------------+-----------------+
| S3cur3P4ssw0rd! |      0 |          0 |          1 |               1 |
| Password        |      0 |          0 |          1 |               1 |
| 42 apples       |      0 |         42 |          0 |               0 |
+-----------------+--------+------------+------------+-----------------+

您可以看到,它首先将密码转换为一个数字,最有可能是0,然后将其与"您的"0值从''--''进行比较,从而成功地进行SQL注入.

Mysql相关问答推荐

SQL条件 Select 和条件WHERE

了解查询中ORDER BY的行为

如何在WooCommerce中更新pm_Virtual.meta_Value=#39;否

如何将左联接的小计/总计行中的所有列作废

在MySQL CLI中,是否有自动完成过程的方法?

为什么 MAX 函数通过调用在 group 中生成正确的结果

MySQL - 事务绑定多个存储过程调用和回滚的简单方法?

如何使用等于、喜欢和不等于在 json 字段上编写查询?

最后一个字母 '%n' 的 mysql SELECT 字符串不起作用

创建将列与多个值进行比较的索引

使用数据表的直方图(SQL 查询)

如何使用 Raw SQl / Laravel 进行累积计数 - Eloquent ORM

如何根据特定条件从mysql数据库中 Select 查询

查询以查找可用时隙

使用 MySQL LIMIT、OFFSET 进行分页

MySQL Group By 和 Sum 其他列的总值

在 PHP 中获取 MySQL 列的总和

在 spring-boot jpa hibernate 中 >4<24 后与 Db 的连接终止

MySQL - 表'my_table'没有被锁定表锁定

判断多个列的一个值