Username: Password:

MySQL安全性指南 (2)(转)
来源:作者: 发布时间:2007-12-19 10:03:55

MySQL安全性指南(2)

作 者: 晏子


2.1.3 数据库和表权限
下列权限运用于数据库和表上的操作。

ALTER
允许您使用ALTER TABLE语句,这其实是个简单的第一级权限,您必须由其他权限,这看您想对数据库实施什么操作。
CREATE
允许您创建数据库和表,但不允许创建索引。
DELETE
允许您从表中删除现有记录。
DROP
允许您删除(抛弃)数据库和表,但不允许删除索引。
INDEX
允许您创建并删除索引。
REFERENCES
现在不用。
SELECT
允许您使用SELECT语句从表中检索数据。对不涉及表的SELECT语句就不必要,如SELECT NOW()或SELECT 4/2。
UPDATE
允许您修改表中的已有的记录。
2.1.4 管理权限
下列权限运用于控制服务器或用户授权能力的操作的管理性操作。

FILE
允许您告诉服务器读或写服务器主机上的文档。该权限不应该随便授予,他很危险,见“回避授权表风险”。服务器确实较谨慎地保持在一定范围内使用该权限。您只能读任何人都能读的文档。您正在写的文档必须不是现存的文档,这防止您迫使服务器重写重要文档,如/etc/passwd或属于别人的数据库的数据目录。
假如您授权FILE权限,确保您不以UNIX的root用户运行服务器,因为root可在文档系统的任何地方创建新文档。假如您以一个非特权用户运行服务器,服务器只能在给用户能访问的目录中创建文档。

GRANT
允许您将您自己的权限授予别人,包括GRANT。
PROCESS
允许您通过使用SHOW PROCESS语句或mysqladmin process命令查看服务器内正在运行的线程(进程)的信息。这个权限也允许您用KILL语句或mysqladmin kill命令杀死线程。
您总是能看到或杀死您自己的线程。PROCESS权限赋予您对任何线程做这些事情的能力。

RELOAD
允许您执行大量的服务器管理操作。您能够发出FLUSH语句,您也能指性mysqladmin的reload、refresh、flush-hosts、flush-logs、flush-privileges和flush-tables等命令。
SHUTDOWN
允许您用mysqladmin shutdown关闭服务器。
在user、db和host表中,每一个权限以一个单独的列指定。这些列全部声明为一个ENUM("N","Y")类型,所以每个权的缺省值是“N”。在tables_priv和columns_priv中的权限以一个SET表示,他允许权限用一个单个列以任何组合指定。这两个表比其他三个表更新,这就是为什么他们使用更有效的表示方式的原因。(有可能在未来,user、db和host表也用一个SET类型表示。)

在tables_priv表中的Table_priv列被定义成:

SET(’Select’,’Insert’,’Update’,’Delete’,’Create’,’Drop’,’Grant’,’References’,’Index’,’Alter’)
在coloums_priv表中的Column_priv列被定义成: 

SET(’Select’,’Insert’,’Update’,’References’)
列权限比表权限少,因为列级较少的权限有意义。例如您能创建一个表,但您不能创建一个孤立的列。

user表包含某些在其他授权表不存在的权限的列:File_priv、Process_priv、Reload_priv和Shutdown_priv。这些权限运用于您让服务器执行的和任何特定数据库或表不相关的操作。如允许一个用户根据当前数据库是什么来关闭数据库是毫无意义的。

2.2 服务器怎样控制客户访问
在您使用MySQL时,客户访问控制有两个阶段。第一阶段发生在您试图连接服务器时。服务器查找user表看他是否能找到一个条目匹配您的名字、您正在从那儿连接的主机和您提供的口令。假如没有匹配,您就不能连接。假如有一个匹配,建立连接并继续第二阶段。在这个阶段,对于每一个您发出的查询,服务器检查授权表看您是否有足够的权限执行查询,第二阶段持续到您和服务器对话的结束。

本小节周详介绍MySQL服务器用于将授权表条目匹配到来的连接请求或查询的原则,这包括在授权表范围列中合法的值的类型、结合授权表中的权限信息的方式和表中条目被检查的次序。

2.2.1 范围列内容
一些范围列需要文字值,但他们大多数允许通配符或其他特别值。

Host
一个Host列值能够是个主机名或一个IP地址。值localhost意味着本地主机,但他只在您用一个localhost主机名时才匹配,而不是您在使用主机名时。假如您的本地主机名是pit.snake.net并且在user表中有对您的两条记录,一个有一个Host值或localhost,而另一个有pit.snake.net,有localhost的记录将只当您连接localhost时匹配,其他在只在连接pit.snake.net时才匹配。假如您想让客户能以两种方式连接,您需要在user表中有两条记录。

您也能够用通配符指定Host值。能够使用SQL的模式字符“%”和“_”并具备当您在一个查询中使用LIKE算符同样的含义(不允许regex算符)。 SQL模式字符都能用于主机名和IP地址。如%wisc.edu匹配任何wisc.edu域内的主机,而%.edu匹配任何教育学院的主机。类似地,192.168.%匹配任何在192.168 B类子网的主机,而192.168.3.%匹配任何在192.168.3 C类子网的主机。

%值匹配任何主机,并可用于允许一个用户从任何地方连接。一个空白的Host值等同于%。(例外:在db表中,一个空白Host值含义是“进一步检查host表”,该过程在“查询访问验证”中介绍。)

从MySQL 3.23起,您也能够指定带一个表明那些为用于网络地址的网络掩码的IP地址,如192.168.128.0/17指定一个17位网络地址并匹配其IP地址是192.168128前17位的任何主机。

User
用户名必须是文字的或空白。一个空白值匹配任何用户。%作为一个User值不意味着空白,相反他匹配一个字面上的%名字,这可能不是您想要的。

当一个到来的连接通过user表被验证而匹配的记录包含一个空白的User值,客户被认为是个匿名用户。

Password
口令值能够是空或非空,不允许用通配符。一个空口令不意味着匹配任何口令,他意味着用户必须不指定口令。

口令以一个加密过的值存储,不是个字面上的文本。假如您在Password列中存储一个照字面上的口令,用户将不能连接!GRANT语句和mysqladmin password命令为您自动加密口令,但是假如您用诸如INSERT、REPLACE、UPDATE或SET PASSWORD等命令,一定要用PASSWORD("new_password")而不是简单的"new_password"来指定口令。

Db
在columns_priv和tables_priv表中,Db值必须是真正的数据库名(照字面上),不允许模式和空白。在db和host中,Db值能够以字面意义指定或使用SQL模式字符’%’或’_’指定一个通配符。一个’%’或空白匹配任何数据库。
Table_name,Column_name
这些列中的值必须是照字面意思的表或列名,不允许模式和空白。
某些范围列被服务器视为大小写敏感的,其余不是。这些原则总结在下表中。特别注意Table_name值总是被看作大小写敏感的,即使在查询中的表名的大小写敏感性对待视服务器运行的主机的文档系统而定(UNIX下是大小写敏感,而Windows不是)。

表3 授权表范围列的大小写敏感性

Host
User
Password
Db
Table_name
Column_name
大小写敏感性
No
Yes
Yes
Yes
Yes
No


2.2.2 查询访问验证
每次您发出一个查询,服务器检查您是否有足够的权限执行他,他以user、db、tables_priv和columns_priv的顺序检查,知道他确定您有适当的访问权限或已搜索任何表而一无所获。更具体的说:

服务器检查user表匹配您开始连接的记录以查看您有什么全局权限。假如您有并且他们对查询足够了,服务器则执行他。
假如您的全局权限不够,服务器为您在db表中寻找并将该记录中的权限加到您的全局权限中。假如结果对查询足够,服务器执行他。
假如您的全局和数据库级组合的权限不够,服务器继续查找,首先在tables_priv表,然后columns_priv表。
假如您在检查了任何表之后仍无权限,服务器拒绝您执行查询的企图。
用布尔运算的术语,授权表中的权限被服务器这样使用:

user OR tables_priv OR columns_priv

您可能疑惑为什么前面的描述只引用4个授权表,而实际上有5个。实际上服务器是这样检查访问权限:

user OR (db AND host) OR tables_priv OR columns_priv

第一个较简单的表达式是因为host表不受GRANT和REVOKE语句影响。假如您总是用GRANT和REVOKE管理用户权限,您绝无需考虑host表。但是其工作原理您用该知道:

当服务器检查数据库级权限时,他对于客户查找db表。假如Host列是空的,他意味着“检查host表以找出哪一个主机能访问数据库”。
服务器在host表中查找有和来自db表的记录相同的Db列值。假如没有host记录匹配客户主机,则没有授予数据库级权限。假如这些记录的任何一个的确有一个匹配连接的客户主机的Host列值,db表记录和host表记录结合产生客户的数据库级权限。
然而,权限用一个逻辑AND(和)结合起来,这意味着除非一个给定的权限在两个表中都有,否则客户就不具备该权限。以这种方式,您能够在db表中授予一个基本的权限集,然后使用host表对特定的主机有选择地禁用他们。如您能够允许从您的域中的任何主机访问数据库,但关闭了那些在较不安全区域的主机的数据库权限。

前面的描述毫无疑问使访问检查听起来一个相当复杂的过程,特别是您以为服务器对您发出的每个查询进行权限检查,然而此过程是很快的,因为服务器其实不从授权表对每个查询查找信息,相反,他在启动时将表的内容读入内存,然后验证查询用的是内存中的副本。这大大提高了访问检查操作的性能。但有一个很明显的副作用。假如您直接修改授权表的内容,服务器将不知道权限的改变。

例如,假如您用一条INSERT语句向user表加入一个新记录来增加一个新用户,命名在记录中的用户将不能连接服务器。这对管理员新手(有时对有经验的老手)是很困惑的事情,当时解决方法很简单:在您改变了他们之后告诉服务器重载授权表内容,您能够发一条FLUSH PRIVILEGES或执行mysqladmin flush-privileges(或假如您有一个不支持flush-privileges的老版本,用mysqladmin reload。)。

2.2.3 范围列匹配顺序
MySQL服务器按一种特定方式排序符授权表中的记录,然后通过按序浏览记录匹配到来的连接。找到的第一个匹配决定了被使用的记录。理解MySQL使用的排序顺序很重要,特别是对user表。

当服务器读取user表内容时,他根据在Host和User列中的值排序记录,Host值起决定作用(相同的Host值排在一起,然后再根据User值排序)。然而,排序不是典序(按词排序),他只是部分是。要牢记的是字面上的词优先于模式。这意味着假如您正从client.your.net连接服务器而Host有client.your.net和%.your.net两个值,则第一个先选。类似地,%.your.net优先于%.net,然后是%。IP地址的匹配也是这样的。

总之一句话,越具体越优先。能够参见本文附录的实例。

2.3 避免授权表风险
本届介绍一些在您授权时的一些预防措施,连同不明值的选择带来的风险。一般地,您要很“吝啬”地授予终极用户权限,即不要启用user表中条目中的权限,而使用其他授权表,以将用户权限限制于数据库、表、或列。在user表中的权限允许于影响到您的服务器操作或能访问任何数据库中的任何表。

不要授予对mysql数据库的权限。一个拥有包含授权表数据库权限的用户可能会修改表以获取对其他任何数据库的权限。授予允许一个用户修改mysql数据库表的权限也实际上给了用户以一个全局GRANT权限。假如用户能直接修改表,这也等价于能够发出任何您能想象的任何GRANT语句。

FILE权限尤其危险,不要轻易授权他。以下是个拥有FILE权限的人能干除的事情:

CREATE TABLE etc_passwd (pwd_entry TEXT);
LOAD DATA INFILE "/etc/passwd" into TABLE etc_passwd;
SELECT * FROM etc_passwd;

在发出这些语句后,用户已拥有了您的口令文档的内容了。实际上,服务器上任何公开可读文档的内容都可被拥有FILE权限的用户通过网络访问。

FILE权限也能被利用来危害没有配置足够权限制的文档权限的系统上的数据库。这就是您为什么应该配置数据目录只能由服务器读取的原因。假如对应于数据库表的文档可被任何人读取,不只是用户服务器账号的用户可读,任何有FILE权限的用户也可通过网络连接并读取他们。下面演示这个过程:

创建一个有一个LONGBLOB列的表:
USER test;
CREATE TABLE tmp (b LONGBLOB);

使用该表读取每个对应于您想偷取的数据库表文档的内容,然后将表内容写入您自己数据库的一个文档中:

LOAD DATA INFILE "./other_db/x.frm" INTO TABLE tmp
FIELDS ESCAPED BY "" LINES TERMINATED BY "";
SELECT * FROM tmp INTO OUTFILE "y.frm"
FIELDS ESCAPED BY "" LINES TERMINATED BY "";
DELETE FROM tmp;
LOAD DATA INFILE "./other_db/x.ISD" INTO TABLE tmp
FIELDS ESCAPED BY "" LINES TERMINATED BY "";
SELECT * FROM tmp INTO OUTFILE "y.ISD"
FIELDS ESCAPED BY "" LINES TERMINATED BY "";
DELETE FROM tmp;
LOAD DATA INFILE "./other_db/x.ISM" INTO TABLE tmp
FIELDS ESCAPED BY "" LINES TERMINATED BY "";
SELECT * FROM tmp INTO OUTFILE "y.ISM"
现在您拥有了一个新表y,他包含other_db.x的内容并且您有全权访问他。
为避免让人以同样的方式攻击,根据“第一部分 内部安全性-保护您的数据目录”中的指令配置您的数据目录上的权限。您也能够在您启动服务器时使用--skip-show-database选项限制用户对于他们没用访问权限的数据库使用SHOW DATABASES和SHOW TABLES。这有助于防止用户找到关于他们不能访问的数据库和表的信息。

ALTER权限能以不希望的方式使用。假定您想让user1能够访问table1但不能访问tables2。一个拥有ALTER权限的用户能够通过使用ALTER TABLE将table2改名为table1来偷梁换柱。

当心GRANT权限。两个由不同权限但都有GRANT权限的用户能够使彼此的权利更强大。

喜欢本文,那就收藏到:

    Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪ViVi 365Key网摘 天极网摘 和讯网摘 博拉网 POCO网摘 添加到饭否 QQ书签 Digbuzz我挖网
相关评论  我也要评论
还没有关于此文章的相关评论!
  • 昵称: (为空则显示guest)
  • 评论分数: ★ ★ ★★★ ★★★★ ★★★★★
  • 评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
  • 导航
    赞助商
    文章类别
    订阅