MySQL:为什么mysql.db中有“测试”条目?


36

最近,我发布了有关mysql.db的问题的答案

然后,我想到我应该问每个人这个问题:

多年以来,我注意到在安装MySQL 5.0+时,其中mysql.db填充了两个条目,允许匿名用户访问测试数据库。

您可以通过运行以下查询来查看它:

mysql> select * from mysql.db where SUBSTR(db,1,4) = 'test'\G
*************************** 1. row ***************************
                 Host: %
                   Db: test
                 User:
          Select_priv: Y
          Insert_priv: Y
          Update_priv: Y
          Delete_priv: Y
          Create_priv: Y
            Drop_priv: Y
           Grant_priv: N
      References_priv: Y
           Index_priv: Y
           Alter_priv: Y
Create_tmp_table_priv: Y
     Lock_tables_priv: Y
     Create_view_priv: Y
       Show_view_priv: Y
  Create_routine_priv: Y
   Alter_routine_priv: N
         Execute_priv: N
*************************** 2. row ***************************
                 Host: %
                   Db: test\_%
                 User:
          Select_priv: Y
          Insert_priv: Y
          Update_priv: Y
          Delete_priv: Y
          Create_priv: Y
            Drop_priv: Y
           Grant_priv: N
      References_priv: Y
           Index_priv: Y
           Alter_priv: Y
Create_tmp_table_priv: Y
     Lock_tables_priv: Y
     Create_view_priv: Y
       Show_view_priv: Y
  Create_routine_priv: Y
   Alter_routine_priv: N
         Execute_priv: N
2 rows in set (0.00 sec)

这些条目是否mysql.db存在安全风险?如果是,为什么将它们默认添加到新安装中?

更新2013-06-14 10:13 EDT

今天早上有人拒绝我的问题,我真的不明白。鉴于此事件,以下是我花时间进行反驳的原因:

本周,我在其暂存群集中为客户端安装了MySQL 5.6.12。我决定检查这是否仍然是一个持续的问题:

mysql> select version();
+------------+
| version()  |
+------------+
| 5.6.12-log |
+------------+
1 row in set (0.00 sec)

mysql> select db,user,host from mysql.db where LEFT(db,4)='test';
+---------+------+------+
| db      | user | host |
+---------+------+------+
| test    |      | %    |
| test\_% |      | %    |
+---------+------+------+
2 rows in set (0.10 sec)

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2013-06-14 10:10:13 |
+---------------------+
1 row in set (0.00 sec)

mysql>

你猜怎么了?直到今天,这仍然是一个问题!

故事的寓意:mysql.db在安装后立即检查您的内容,并删除匿名登录名并立即删除这些测试条目mysql.db


8
+1可解决此问题。我以前从未注意到它,但是我始终mysql_secure_installation在全新安装上运行,该安装将删除匿名用户。
德里克·唐尼

Answers:


30

请注意哪些MySQL 5.0认证学习指南

在此处输入图片说明

在第498页第6段的要点中说:

在Unix上,MySQL附带了一个mysql_secure_installation脚本,该脚本可以对您的安装执行一些与安全性有关的有用操作。该脚本具有以下功能:

  • 为root帐户设置密码
  • 删除所有可远程访问的根帐户。
  • 删除匿名用户帐户。这样可以提高安全性,因为它可以防止任何人以root用户身份从远程主机连接到MySQL服务器。结果是任何想以root用户身份连接的人都必须首先能够登录服务器主机,这为攻击提供了额外的障碍。
  • 删除测试数据库(如果删除匿名帐户,您可能还希望删除它们有权访问的测试数据库)。

要清除这些错误的条目,请运行以下命令:

DELETE FROM mysql.db WHERE SUBSTR(db,4) = 'test';
FLUSH PRIVILEGES;

正如@DTest在他对问题的评论中提到的那样,您也可以为此运行mysql_secure_installation

如果匿名用户可以远程登录MySQL,则可以发起简单的磁盘攻击来破坏mysql的安装。这是一个例子:

USE test
CREATE TABLE rolando_tb (a int);
INSERT INTO rolando_tb VALUES (1);
INSERT INTO rolando_tb SELECT a FROM rolando_tb;
INSERT INTO rolando_tb SELECT a FROM rolando_tb;
INSERT INTO rolando_tb SELECT a FROM rolando_tb;
INSERT INTO rolando_tb SELECT a FROM rolando_tb;

运行insert 30次,您将获得一个7GB的表

  • 想象一下在测试数据库中创建其中几个表
  • 想象一下在测试数据库中创建存储过程
  • 只要test和test_%存在于 mysql.db

MySQL AB尚未完全记录确保mysql安装安全的严重性,而且我认为Oracle今天没有兴趣这样做。

更新2012-02-18 16:45 EDT

@atxdba的评论建议仅运行“ DROP DATABASE测试”;应该是优先于接触mysql.db的方法。删除名为的数据库test仅会删除打开潜在安全漏洞通道的数据库。

请注意此查询:

mysql> select user,host,db from mysql.db;
+------+------+---------+
| user | host | db      |
+------+------+---------+
|      | %    | test    |
|      | %    | test\_% |
+------+------+---------+
2 rows in set (0.09 sec)

基于此,匿名用户可以完全访问以下数据库:

  • 测试
  • test_db
  • test_001
  • test_1
  • 测试数据

虽然匿名用户无法完全访问以下数据库:

  • 测试数据库
  • 测试1
  • 测试数据
  • 测试(Test不同于test在基于Linux的系统,但它仍然是问题的MySQL在Windows上运行)

您将不得不记住基于mysql.db表的这一细微规则。如果您不记得这一点,则创建一个名为的测试数据库test或名称的前5个字符的数据库名称test_将重新打开相同类型的安全漏洞。

记住这些事情的最安全的方法是在初始安装后运行以下行:

DELETE FROM mysql.db WHERE SUBSTR(db,4) = 'test' AND user='';
FLUSH PRIVILEGES;

那么任何名称的数据库都可以进行正确的身份验证设置。您仍然可以随时运行这两行。

更新2012-02-24 15:20 EDT

为了公开展示在中拥有匿名用户的危险mysql.db,我想创建一个仅具有使用权限的用户。

我将在桌面上使用MySQL 5.5.12

首先,看一下mysql.db

mysql> select user,host,db from mysql.db;
+------+------+---------+
| user | host | db      |
+------+------+---------+
|      | %    | test    |
|      | %    | test\_% |
+------+------+---------+
2 rows in set (0.05 sec)


mysql>

据此,任何匿名的Joe都可以访问这些数据库。

我将创建一个数据库test_mysqldb

mysql> create database test_mysqldb;
Query OK, 1 row affected (0.00 sec)

mysql> use test_mysqldb
Database changed
mysql> show tables;
Empty set (0.00 sec)

mysql>

让我们创建一个普通的香草用户,名为vanilla @ localhost(无密码)

mysql> CREATE USER vanilla@localhost;
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW GRANTS FOR vanilla@localhost;
+---------------------------------------------+
| Grants for vanilla@localhost                |
+---------------------------------------------+
| GRANT USAGE ON *.* TO 'vanilla'@'localhost' |
+---------------------------------------------+
1 row in set (0.00 sec)

mysql>

接下来,从DOS命令行中,让我们连接到mysql模式

C:\>mysql -uvanilla -Dmysql
ERROR 1044 (42000): Access denied for user 'vanilla'@'localhost' to database 'mysql'

C:\>

好的,不错。这就是我的期望。

接下来,从DOS命令行,让我们连接到test_mysqldb模式,创建一个表,并用数字加载它

C:\>mysql -uvanilla -Dtest_mysqldb
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.5.12-log MySQL Community Server (GPL)

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> CREATE TABLE rolando_tb (a bigint unsigned);
Query OK, 0 rows affected (0.06 sec)

mysql> INSERT INTO rolando_tb VALUES (1);
Query OK, 1 row affected (0.06 sec)

mysql> INSERT INTO rolando_tb SELECT * FROM rolando_tb;
Query OK, 1 row affected (0.06 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> INSERT INTO rolando_tb SELECT * FROM rolando_tb;
Query OK, 2 rows affected (0.08 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> INSERT INTO rolando_tb SELECT * FROM rolando_tb;
Query OK, 4 rows affected (0.06 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> INSERT INTO rolando_tb SELECT * FROM rolando_tb;
Query OK, 8 rows affected (0.06 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM rolando_tb;
+------+
| a    |
+------+
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
|    1 |
+------+
16 rows in set (0.00 sec)

mysql> SELECT database();
+--------------+
| database()   |
+--------------+
| test_mysqldb |
+--------------+
1 row in set (0.00 sec)

mysql>

你看到了吗?具有USAGE特权的用户可以在测试数据库中创建一个表,并在其中填充数据。这是一个明显的当前危险。这就是为什么我强烈建议从mysql.db中删除那些测试条目,以阻止匿名用户访问测试数据库或访问新创建的测试数据库(通过在默认情况下创建子文件夹datadir)。

提醒一下,这是您的操作方式:

DELETE FROM mysql.db WHERE SUBSTR(db,4) = 'test' AND user='';
FLUSH PRIVILEGES;

更新2013-09-14 20:05 EDT

为了证明DELETE FROM mysql.db WHERE SUBSTR(db,4) = 'test' AND user='';实际可行,我今天在MySQL 5.6.13上运行了该命令:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.13-log MySQL Community Server (GPL)

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select db,user,host from mysql.db where LEFT(db,4)='test';
+---------+------+------+
| db      | user | host |
+---------+------+------+
| test    |      | %    |
| test\_% |      | %    |
+---------+------+------+
2 rows in set (0.43 sec)

mysql> delete from mysql.db where LEFT(db,4)='test';
Query OK, 2 rows affected (0.04 sec)

mysql> select db,user,host from mysql.db2 where LEFT(db,4)='test';
Empty set (0.00 sec)

mysql>

就像公共服务公告一样,请运行

DELETE FROM mysql.db WHERE SUBSTR(db,4) = 'test' AND user='';
FLUSH PRIVILEGES;

或仅运行mysql-secure-installation并将此潜在危险置于一身。


不放弃数据库测试;与直接烦躁与mysqldb首选?从db表中删除该条目不会删除实际的测试db目录。如果没有什么比这看起来更适合做家务了
atxdba 2012年

1
我必须DELETE from mysql.db WHERE Db LIKE 'test%';注意字段名称的大小写很重要。所以,如果你的字段名称Db不是 db,上面的查询将无法正常工作。
艾利(Avery)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.