我们的 VPS 设置方式是,所有数据库都可以通过本地主机和用户名/密码/数据库名称从任何域访问。
这是通常的设置吗,或者应该有某种方式来“监禁”每个用户,以便他们无法访问本地主机上的其他数据库?
谢谢,马克
答案1
正如 Caleb 提到的,在设置 MySQL 时,最好像其他系统一样,运行最低权限系统 - 除非不同的应用程序相关,否则它们没有理由访问彼此的数据库。如果一些是相关,那么他们应该被授予特定的,有限的他们需要访问其他数据库中的表的权限,但仅此而已。
我假设你说
可以通过 localhost 从任何域访问
您的意思是您正在运行多域 Apache 安装(或类似安装),这意味着您的所有应用程序都在同一台机器上运行,因此,从 MySQL 的角度来看,每个用户都是一个'username'@'localhost'
用户,所以您只能通过用户名指定用户。
需要注意的是,由于 MySQL 权限的工作方式,在有远程用户的情况下,这'user1'@'abc.example.com'
实际上是完全不同的用户或'user1'@'xyz.example.com'
尽管'user1'@'localhost'
共享用户名确实会大大增加您设置权限的灵活性(或者使事情变得非常混乱,这取决于您的观点)。如果可以的话,最好在不同的虚拟机上运行数据库服务器 - 当然这不是必须的。
添加数据库用户的常见、易于使用(但不安全)的方法往往是这样的:
GRANT ALL ON *.* TO `user1`@`localhost`;
这只是授予该用户GLOBAL
在任何数据库上执行任何操作的权限。
这很糟糕,原因显而易见,但也并不那么明显。*.*
包括mysql
数据库本身 - 它允许您执行任何事物您喜欢与其他用户、设置等共享权限,应避免这种情况。ALL
语句的一部分授予GLOBAL
范围内可用的所有权限 - 这意味着他们可以执行诸如SHOW PROCESSLIST
和之类的操作KILL <query-id>
。这似乎没什么问题(“他们为什么要这样做?”)但正如 Caleb 所说 - 如果应用程序受到攻击,它连接的数据库用户就是攻击者“用来对付”您的用户。
对上述内容的一个简单改进是使用如下语句为每个数据库分配权限:
GRANT ALL ON `user1_database`.* TO `user1`@`localhost`;
这将授予所有级别DATABASE
的权限- 这很重要,因为它排除了上面列出的所有强大的权限,所以现在用户最坏的情况是删除自己的数据库。user1
user1_database
GLOBAL
这种方法的进一步改进是为每个应用程序创建至少两个用户。一个拥有GRANT ALL
数据库权限(用于管理),另一个由 Web 应用程序本身使用,该用户仅拥有所需的权限,并且仅拥有需要访问的对象。当您进行更改和额外测试时,这显然需要相当多的额外工作,但做得好可以大大减少系统受到损害时可能造成的损害。
我通常有一个标准用户,以及另一个带有_www
Web 应用程序后缀的用户。
你可以使用 MySQL 的通配符权限来简化其中的一些操作,并让用户可以创建自己的数据库(匹配特定的模式)并
例子
-- Create a user that has ALL privileges on databases beginning with 'user1_'
-- This is our application admin user
-- it can create any database that matches the pattern
GRANT ALL ON `user1\_%`.* TO `user1`@`localhost`;
-- Create a "safe" version of this user with just the ability to modify data
-- This is a generic approach and could be applied at object level per-database
GRANT SELECT, INSERT, UPDATE, DELETE ON `user1\_%`.* TO `user1_www`@`localhost`;
示例中创建管理员用户的方式是共享环境中的常用方法 - 它允许用户创建数据库,而无需分配任何GLOBAL
权限,以便他们看不到其他用户的数据库。
答案2
您应该使用 MySQL 权限表来设置更细粒度的权限,以便每个应用程序(甚至是应用程序的组件)只能访问其功能所需的数据库或表。这将减少隐私侵犯的潜在问题,减少发生安全漏洞时的损失,甚至有助于在测试期间发现软件中的错误。
答案3
正如 @simon 和 @caleb 提到的,授予全局权限是很常见的,但这并不意味着它是一种好的做法,我使用这个“宏”(这是我根据 serverfault 或 SO 上的另一篇文章拼凑起来的,但我不记得是哪一个了)来获得权限:
SET @usr = '\'username\'@\'localhost\'';
SET @pwd = '\'longpassword\'';
SET @db = 'database';
set @query = CONCAT('revoke all privileges on *.* from ', @usr);PREPARE stmt FROM @query;EXECUTE stmt;DEALLOCATE PREPARE stmt;
set @query = CONCAT('drop user ', @usr);PREPARE stmt FROM @query;EXECUTE stmt;DEALLOCATE PREPARE stmt;
set @query = CONCAT('create user ', @usr, ' identified by ', @pwd);PREPARE stmt FROM @query;EXECUTE stmt;DEALLOCATE PREPARE stmt;
set @obj = CONCAT(@db, '.tablename');SET @query = CONCAT('GRANT select ON ', @obj, ' TO ', @usr, ' identified by ', @pwd);PREPARE stmt FROM @query;EXECUTE stmt;DEALLOCATE PREPARE stmt;
删除“撤销”、“删除”和“创建”行,并根据需要更改表名和权限。正如@caleb 所建议的那样,它允许以最少的麻烦创建细粒度的权限。