MySQL: Por que existem entradas "test" no mysql.db?

37

Recentemente, postei uma resposta para uma pergunta sobre o mysql.db .

Então, comecei a pensar que deveria fazer a todos esta pergunta:

Eu notei há anos que, após a instalação do MySQL 5.0+, mysql.dbé preenchida com duas entradas que permitem que os bancos de dados de teste sejam acessados ​​por usuários anônimos.

Você pode vê-lo executando esta consulta:

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)

Essas entradas representam mysql.dbum risco de segurança e, em caso afirmativo, por que são adicionadas por padrão a uma nova instalação?

UPDATE 2013-06-14 10:13 EDT

Hoje de manhã alguém votou na minha pergunta, o que eu realmente não entendo. À luz deste evento, eis o motivo pelo qual dediquei um tempo para fazer uma refutação:

Eu instalei o MySQL 5.6.12 para um cliente esta semana no Cluster de armazenamento temporário. Decidi verificar se este ainda era um problema contínuo:

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>

Adivinha? Ainda é um problema até hoje !!!

MORAL DA HISTÓRIA: Verifique seu mysql.dbimediatamente após a instalação, remova logons anônimos e apague essas entradas de teste mysql.dbsem demora.

RolandoMySQLDBA
fonte
8
+1 por trazer esse problema à tona. Eu nunca percebi isso antes, mas sempre executo mysql_secure_installationuma instalação nova, que remove os usuários anônimos.
Derek Downey

Respostas:

30

Observe o Guia de Estudo da Certificação MySQL 5.0

insira a descrição da imagem aqui

digamos em seus tópicos no parágrafo 6º:

No Unix, o MySQL vem com um script mysql_secure_installation que pode executar várias operações úteis relacionadas à segurança em sua instalação. O script possui os seguintes recursos:

  • Defina uma senha para as contas raiz
  • Remova todas as contas raiz acessíveis remotamente.
  • Remova as contas de usuário anônimas. Isso melhora a segurança porque evita a possibilidade de alguém se conectar ao servidor MySQL como root a partir de um host remoto. O resultado é que quem deseja se conectar como root deve primeiro fazer logon no host do servidor, o que fornece uma barreira adicional contra ataques.
  • Remova o banco de dados de teste (se você remover as contas anônimas, também poderá remover o banco de dados de teste ao qual elas têm acesso).

Para se livrar dessas entradas incorretas, execute isso por favor:

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

Como o @DTest mencionado em seu comentário à pergunta, você também pode executar o mysql_secure_installation para você.

Se um usuário anônimo puder acessar o MySQL remotamente, um simples ataque de disco poderá ser iniciado para prejudicar a instalação do mysql. Aqui está um exemplo:

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;

Execute a inserção 30 vezes e você obterá uma tabela de 7 GB

  • Imagine criar várias dessas tabelas no banco de dados de teste
  • Imagine criar um procedimento armazenado no banco de dados de teste
  • As possibilidades são infinitas, desde que test e test_% existam em mysql.db

A seriedade de proteger a instalação do mysql não foi totalmente documentada pela MySQL AB, e não acho que a Oracle esteja interessada em fazê-lo hoje.

UPDATE 2012-02-18 16:45 EDT

Foi sugerido pelo comentário de @ atxdba que apenas executando 'DROP DATABASE test;' deve ser o método preferido em vez de tocar em mysql.db. A eliminação do banco de dados nomeado testsimplesmente remove o banco de dados que abre um canal para uma possível falha de segurança.

Observe esta consulta:

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

Com base nisso, os seguintes bancos de dados podem ser acessados ​​totalmente por usuários anônimos :

  • teste
  • test_db
  • test_001
  • test_1
  • dados de teste

Embora os seguintes bancos de dados não possam ser acessados ​​completamente por usuários anônimos:

  • testdb
  • test1
  • dados de teste
  • Teste ( Testé diferente dos testsistemas baseados em Linux, mas ainda é um problema para o MySQL em execução no Windows)

Você precisará se lembrar desta regra sutil com base na mysql.dbtabela. Se você não se lembrar disso, a criação de um banco de dados de teste chamado testou um nome de banco de dados cujos 5 primeiros caracteres sejam test_reabrirá o mesmo tipo de falha de segurança.

A maneira mais segura de se lembrar dessas coisas é executar essas linhas após uma instalação inicial:

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

qualquer banco de dados com qualquer nome pode ter uma configuração de autenticação adequada. Você ainda pode executar essas duas linhas a qualquer momento.

ATUALIZAÇÃO 24/02/2012 15:20 EDT

Para demonstrar abertamente o perigo de ter usuários anônimos mysql.db, gostaria de criar um usuário que tenha apenas o privilégio de uso.

Vou usar o MySQL 5.5.12 na minha área de trabalho

Primeiro, veja o mysql.db

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


mysql>

De acordo com isso, qualquer Joe anônimo pode acessar esses bancos de dados.

Vou criar um banco de dados 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>

Vamos criar um usuário simples de baunilha chamado vanilla @ localhost (sem senha)

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>

Em seguida, na linha de comando do DOS, vamos nos conectar ao esquema mysql

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

C:\>

OK ótimo. Era o que eu esperava.

Em seguida, na linha de comando do DOS, vamos nos conectar ao esquema test_mysqldb, criar uma tabela e carregá-la com números

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>

Você viu aquilo? Um usuário comUSAGEprivilégio pode criar uma tabela em um banco de dados de teste e preenchê-la com dados. Este é um perigo claro e presente . É por isso que recomendo excluir essas entradas de teste do mysql.db para impedir que usuários anônimos cheguem a bancos de dados de teste ou acessem bancos de dados de teste recém-criados (criando uma subpasta como padrãodatadir).

Como lembrete, é assim que você faz:

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

UPDATE 2013-09-14 20:05 EDT

Para demonstrar que DELETE FROM mysql.db WHERE SUBSTR(db,4) = 'test' AND user='';realmente funciona, executei isso no MySQL 5.6.13 hoje:

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>

Assim como um anúncio de serviço público, execute

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

ou apenas execute o mysql-secure-installation e coloque esse perigo em potencial.

RolandoMySQLDBA
fonte
Não é descartado o teste do banco de dados; preferido sobre mexer diretamente com o mysqldb? Excluir a entrada da tabela db não removerá o diretório db de teste real. Se nada mais que apenas parece ser melhor do house keeping
atxdba
1
Eu tive que fazer uma DELETE from mysql.db WHERE Db LIKE 'test%';anotação de que a capitalização do nome do campo é importante. Portanto, se o nome do seu campo for Dbe não db , a consulta acima não funcionará.
Avery