最近,我发布了一个有关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中的这些条目是否存在安全风险,如果存在,为什么默认情况下将它们添加到新安装中?

UPDATE 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清除这些测试条目,不要拖延。

评论

+1可解决此问题。我以前从未注意到它,但是我总是在全新安装上运行mysql_secure_installation,该操作会删除匿名用户。

#1 楼

请注意《 MySQL 5.0认证研究指南》



在第498页第6段的项目点中的说法:


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


设置根帐户的密码
删除所有可远程访问的根帐户。
删除匿名用户帐户。这提高了安全性,因为
防止了任何人以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;


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


想象一下创建其中几个表在测试数据库中
想象一下在测试数据库中创建存储过程
只要mysql.db中存在test和test_%,可能性是无限的


保护MySQL安装的安全性尚未得到MySQL AB的完整记录,我认为Oracle今天没有兴趣这样做。

UPDATE 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
test_db
test_001
test_1
test_data

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


testdb
test1
testdata
Test(Test是与基于Linux的系统中的test不同,但是对于Windows中运行的MySQL来说仍然是问题)

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

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

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


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

UPDATE 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-2-18 14:08



我不得不从mysql.db那里删除,比如Db'test%';请注意,字段名称的大小写很重要。因此,如果您的字段名称是Db而不是db,则上面的查询将不起作用。

–每个
2013年9月13日在7:07