您的位置:首页 > 博客中心 > 数据库 >

[MySQL Reference Manual] 6 安全性

时间:2022-03-13 22:38

CREATE USER ... IDENTIFIED BY ...

GRANT ... IDENTIFIED BY ...

SET PASSWORD ...

SLAVE START ... PASSWORD = ...              (as of 5.6.4)

CREATE SERVER ... OPTIONS(... PASSWORD ...) (as of 5.6.9)

ALTER SERVER ... OPTIONS(... PASSWORD ...)  (as of 5.6.9)

 

语句中的密码不会出现在,general query log,slow query log,binary log。general query log的password 重写可以使用—log-raw选项来限制。(使用mariadb 10.0测试无效)。

审计日志的文本是不加密的,所以不能让其他用户访问。

为了尽量避免日志内容保留,应该不能让系统和数据库管理员之外的用户访问日志文件。

复制slave在master info repository中保存了复制master的密码,会存在一个文件或者一个表中。要保证repository只能被数据库管理员读取。

6.1.2.4 Mysql中的密码hash

mysql的用户存放在mysql.user下,每个账号都有一个密码,密码是以hash值存放的。

mysql,在client和server交互的2个阶段用到密码:

1.client连接会把密码的hash,然后和user表的密码进行匹配

2.在登陆之后,可以修改密码。

 

原先的hash方法(4.1版本之前)会产生16字节的字符串。4.1版本之后的hash方法产生41字节的字符串并且密码以*号开头。

使用old_password()就是使用老的hash方法。当old_password变量为1是,password函数产生的结果16字节长度。

6.1.2.5 mysql 4.1的应用程序的密码hash修改实现

6.1.2.6 密码验证插件

validate_password(5.6.6之后),用来测试密码的安全性。这个插件有2个功能:

1.检查密码明文的密码策略

2.通过长度看密码强壮性。

如果使用密码明文,那么就会对密码进行验证,如果直接用hash值,那么就不验证。

 

密码验证插件安装方法:

1.使用配置文件

[mysqld]

plugin-load=validate_password.so

2.使用instal plugin命令,使用后会在mysql.plugins表中加入记录,下次启动会自动加载。

mysql> INSTALL PLUGIN validate_password SONAME ‘validate_password.so‘;

validate-password可以用来控制服务启动的时候加载插件,如果值是FORCE或者FORCE_PLUS_PERMANENT,如果插件初始化失败,那么服务启动就失败。

6.1.3 防止Mysql被攻击

mysql在传输的时候密码不是明文传输的,但是其他信息都是明文,可能会被其他人读取,如果是和非信任网络的交互,可以使用ssl加密连接。

有以下几点可以让mysql系统更加安全:

1.每个mysql用户都要有密码

2.只有mysqld的启动用户有访问数据库文件夹的权限

3.不要用root用户启动mysql服务。这样每个连接都有服务器上的root权限,十分危险。

4.不要授予非管理员用户FILE权限

5.不要授予非管理员用户PROCESS和SUPER权限

6.不允许使用symlink到表。

7.存储过程和函数要在安全指导写编写,.

8.在权限表中,如果对DNS不信任,那么就使用ip地址

9.如果要限制一个账号的最大连接数,可以使用max_user_connections变量。

6.1.4 安全相关的mysqld选项和变量

Name

Cmd-Line

Option file

System Var

Status Var

Var Scope

Dynamic

ERROR 1148: The used command is not allowed with this MySQL version

6.1.7客户端程序安全性

6.2 mysql访问权限系统

mysql权限系统主要有2个功能:

1.给验证用户权限

2.给你匿名用户权限

权限系统中不能做的事:

Privilege

Column

Context

Create_priv

databases, tables, or indexes

Drop_priv

databases, tables, or views

Grant_priv

databases, tables, or stored routines

Lock_tables_priv

databases

References_priv

databases or tables

Event_priv

databases

Alter_priv

tables

Delete_priv

tables

Index_priv

tables

Insert_priv

tables or columns

Select_priv

tables or columns

Update_priv

tables or columns

Create_tmp_table_priv

tables

Trigger_priv

tables

Create_view_priv

views

Show_view_priv

views

Alter_routine_priv

stored routines

Create_routine_priv

stored routines

Execute_priv

stored routines

File_priv

file access on server host

Create_tablespace_priv

server administration

Create_user_priv

server administration

Process_priv

server administration

see proxies_priv table

server administration

Reload_priv

server administration

Repl_client_priv

server administration

Repl_slave_priv

server administration

Show_db_priv

server administration

Shutdown_priv

server administration

Super_priv

server administration

 

server administration

 

server administration

6.2.2 权限系统权限表

通常操作权限表是通过,grant,revoke来间接操作的。

mysql的表中一下表包含权限信息:

user:包含了用户账号,全局权限和其他权限列

db:数据库级别权限

host:mysql5.6.7之后就不存在,mariadb10.0也不存在

tables_priv:表级权限

columns_priv:列级权限

procs_priv:存储过程和函数权限

proxies_priv:代理用户权限

 

每个权限表包含适用范围列和权限列:

1.适用范围列决定了权限适用范围。

2.权限列表明了被授予的权限。

服务会在以下方式使用权限表:

1.user表的范围列决定了是拒绝或者允许连接。对于可连接的用户,在users表的权限都是全局权限,可以应用到所有数据库。

2.db表范围列确定了用户可以确定了从哪来的连接可以访问哪些数据库

3.tables_priv和columns_priv表和db表类似,但是粒度更加小,应用在表级和列级。

4.procs_priv应用在存储过程和函数的权限

5.proxies_priv表说明用户可以代理其他用户

具体权限表的表接口可以看:

6.2.3 指定帐号(Account)名

帐号名规则:

1.帐号名规则是user_name@host_name

2.若指定一个用户名,就相当于’user_name’@’%’

3.如果不用引号合法,可以不用引号

4.用户名可以使用单引号,双引号,或者(`)

5.引号的添加方法不是’user_name@%’,是’user_name’@’%’

6.使用current_user或者current_user()获取当前用户名和host。

 

host是帐号的一部分可以有很多方式和通配符:

1.host可以指定hostname或者ip地址(ipv4,ipv6)。

2.你可以使用’%’或者’’替换host或者ip地址。

3.也可以使用host_ip/netmask格式代替host_name。

6.2.4 访问控制,阶段1:连接验证

当用户连接到mysql,通过了identity认证,则进入阶段2。

identity由2部分组成:

1.客户端host名

2.mysql用户名

identity的验证需要用到user表的3个字段,host,user,password。

如果user列不是空的,只能准确的匹配,如果user列是空的,可以匹配任意用户。若user表中的一行匹配了一个空用户名的用户,那么这个用户就被认为是匿名用户,不是指定用户名的用户。

password列如果为空的,并不意味着通配,而是空密码。如果plugin认证可以使用密码也可以不使用密码。如果password不是为空的,那么说明登陆的时候需要密码验证。

 

当连接的时候有多个可以匹配,就用以下方法:

1.不管什么时候服务读取user表到内存,会对行排序

2.当一个客户端视图连接,服务会通过排序的顺序匹配

3.服务会使用第一个匹配的username和hostname

排序,越准确的排在越前面。

如:

+-----------+----------+-             

| Host       | User     | ...

+-----------+----------+-

| %           | root     | ...

| %           | jeffrey  | ...

| localhost | root     | ...

| localhost |          | ...

+-----------+----------+-

排序后:

+-----------+----------+-

| Host      | User     | ...

+-----------+----------+-

| localhost | root     | ...

| localhost |          | ...

| %         | jeffrey  | ...

| %         | root     | ...

+-----------+----------+-

如果连接了,但是不是自己要的帐号,可以使用current_user()查看匹配的用户。

6.2.5 访问控制,阶段2:请求验证

连接之后,服务进入第二阶段,当客户端请求,服务就会去检查是否有权限来执行这个请求。权限可以通过表,user,db,tables_priv,columns_priv,procs_priv检查。

 

user表的权限是全局的适用于所有数据库。

在db表中:

1.空的用户名表示匿名用户,非空的表示指定用户

2.通配符和’’可以用在host和db列

3.’%’或者空的host表示任意host

4.’%’或者空的db表示任意数据库

db表通过host,db,user排序。

 

对于tables_priv,columns_priv,procs_priv:

1.host列可以有通配符

2.‘%‘或者空host表示任意host

3.db,table_name,column_name,routine_name列不能包含通配符或者空。

这几个表也是根据host,db,user排序。

 

对于数据库相关的请求,先看用户全局user表,若没有就查db表的权限。server查看db表,同难过host,db,user列进行匹配。

 

在确定指定数据库的权限,服务把权限添加到全局权限中,如果满足了就执行,如果不满足服务检查用户表和列的权限(tables_priv,columns_priv)把这些添加到用户权限,根据结果来确定是否执行。

 

权限的计算类似于这样:

global privileges

OR (database privileges AND host privileges)

OR table privileges

OR column privileges

OR routine privileges

但是如果出现一个请求需要多个权限的情况下,就不是这样。

6.2.6 权限修改生效时间

mysql启动会读取grant表到内存,这个时候才生效。

如果使用grant,revoke,setpassword,rename user间接的修改权限,服务会注意到时修改权限并会马上加载到内存。

 

若使用dml修改权限表,需要手动加载后才能生效。重新加载的方法:

1.flush privileges语句

2.mysqladmin flush-privilege

3.mysqladmin reload

权限生效之后会对每个存在的客户端影响:

1.表或者列权限修改,会影响客户端下一个请求

2.数据库权限修改会影响下一个use db_name语句

3.全局权限修改会影响下一个连接

如果在启动服务的时候使用—skip-grant-tables选线,不会读取权限表,不会对权限进行认证,可以随意访问数据。

6.2.7 访问拒绝的例子

具体可以看:

6.3 MySQL用户帐号管理

6.3.1用户名和密码

mysql的帐号保存在user表中,帐号由用户名和host组成。

mysql> GRANT USAGE ON *.* TO ‘francis‘@‘localhost‘

    ->     WITH MAX_QUERIES_PER_HOUR 100;

如果要删除限制就设置为0:

mysql> GRANT USAGE ON *.* TO ‘francis‘@‘localhost‘

    ->     WITH MAX_CONNECTIONS_PER_HOUR 0;

如果grant设置的MAX_USER_CONNECTIONS会覆盖系统变量如:

max_user_connections=10

GRANT ... TO ‘user1‘@‘localhost‘ WITH MAX_USER_CONNECTIONS 0;
GRANT ... TO ‘user2‘@‘localhost‘ WITH MAX_USER_CONNECTIONS 5;
GRANT ... TO ‘user3‘@‘localhost‘ WITH MAX_USER_CONNECTIONS 20;

那么user1的最大并发连接数为10,user2为5,user3为20。

 

在user表中的,max_query,max_update,max_connections,存放了每小时的限制。max_user_connections存放了并发连接数的限制。

 

以下2个语句会重置所有帐号的限制:

1.使用flush user_resources语句

2.使用grant usage设置修改限制

6.3.5 设置密码

密码设置可以在create user中也可以set password:

mysql> CREATE USER ‘jeffrey‘@‘localhost‘
    -> IDENTIFIED BY ‘mypass‘;
mysql> SET PASSWORD FOR
    -> ‘jeffrey‘@‘localhost‘ = PASSWORD(‘mypass‘);

read_only变量可以阻止没有有SPUER权限的用户使用 set password。

 

还可以使用grant usage on *.*来设置密码:

mysql> GRANT USAGE ON *.* TO ‘jeffrey‘@‘localhost‘
    -> IDENTIFIED BY ‘mypass‘;

或者使用mysqladmin:

shell> mysqladmin -u user_name -h host_name password "newpwd"

 

设置密码的时候注意点:

1.当使用create user或者grang identified by语句的时候可以直接使用明文,服务会帮助加密

2.当使用identified by password那么需要自己先使用password()加密

3.当使用set password 的时候,要自己调用password()加密

 

当然可以直接修改user表,但是需要执行flush privileges。

6.3.6 密码过期和沙盘模式

6.3.6.1 密码过期工作原理

密码过期是mysql 5.6新加的功能。(在mariadb中也有password_expired但是完成不了,下面说的功能)。

用alter user 来手动过期一个用户:

ALTER USER ‘myuser‘@‘localhost‘ PASSWORD EXPIRE;

执行了之后,mysql.user.password_expired变为Y。下次连接的时候用户要不进入沙盘模式,要不就无法连接。

如果进入了沙盘模式,用户只允许做:

1.set password修改密码

2.set语句

其他的操作都会被拒绝。

 

disconnect_on_expired_password用来判断如何处理过期帐号的连接。如果为yes,就无法连接到客户端,为no连接到客户端,并进入沙盘模式。

 

6.3.7 插件式验证(Pluggable Authentication)

当客户端连接到mysql服务,根据指定的验证插件来验证:

1.如果指定了验证插件,那么就用验证插件验证

2.如果没有指定验证插件,根据password的hash值,确定使用mysql_native_password还是使用mysql_old_password

插件式的验证方式,带来了2个功能:

1.可扩展验证,就是可以通过其他验证插件来验证用户登录

2.代理用户,可以让登录用户伪装成其他用户执行请求

6.3.7.1 验证插件的使用方法

1.安装插件的library到server和client

2.安装插件,可以以配置文件,也可以用install plugin

[mysqld]
plugin-load=test_plugin_server=auth_test_plugin.so
mysql> INSTALL PLUGIN test_plugin_server SONAME ‘auth_test_plugin.so‘;

install plugin只要运行一次就可以,下次启动会自动加载插件。

3.验证插件是否安装

mysql> SHOW PLUGINS\G
...
*************************** 21. row ***************************
   Name: test_plugin_server
 Status: ACTIVE
   Type: AUTHENTICATION
Library: auth_test_plugin.so
License: GPL

4.设置帐号的验证插件

CREATE USER ‘testuser‘@‘localhost‘ IDENTIFIED WITH test_plugin_server;

5.使用客户端连接

 

当用户连接验证的时候,服务发现是使用auth_test_plugin插件验证,那么服务端和客户端交流使用 auth_test_plugin,来验证。

 

6.3.8 MySQL中可用的验证插件

具体看文档:

6.3.9 代理用户(proxy user)

代理用户是a用户登录但是使用b用户的权限执行请求。a用户就是代理用户(proxy user),b用户就是被代理用户(proxied user)。

要使用代理用户必须满足:

1.当连接客户端被当做是代理用户,插件必须返回一个不同的用户名(proxied user)。

2.代理用户帐号必须有插件验证

3.代理用户必须有代理 proxied用户的权限。

如:

CREATE USER ‘empl_external‘@‘localhost‘
  IDENTIFIED WITH auth_plugin AS ‘auth_string‘;
CREATE USER ‘employee‘@‘localhost‘
  IDENTIFIED BY ‘employee_pass‘;
GRANT PROXY
  ON ‘employee‘@‘localhost‘
  TO ‘empl_external‘@‘localhost‘;

当登录empl_external@localhost,使用current_user()返回:

mysql> SELECT USER(), CURRENT_USER();
+-------------------------+--------------------+
| USER()                  | CURRENT_USER()     |
+-------------------------+--------------------+
| empl_external@localhost | employee@localhost |
+-------------------------+--------------------+

是否 要用identified with as由插件决定。

6.3.9.1授予PROXY权限

PROXY权限通过 grant proxy语句被授予

GRANT PROXY ON ‘proxied_user‘ TO ‘proxy_user‘;

和revoke proxy对于

REVOKE PROXY ON ‘proxied_user‘ FROM ‘proxy_user‘;

 

6.3.9.2 默认proxy用户

如:

CREATE USER ‘‘@‘‘ IDENTIFIED WITH ldap_auth AS ‘O=Oracle, OU=MySQL‘;
CREATE USER ‘developer‘@‘localhost‘ IDENTIFIED BY ‘developer_pass‘;
CREATE USER ‘manager‘@‘localhost‘ IDENTIFIED BY ‘manager_pass‘;
GRANT PROXY ON ‘manager‘@‘localhost‘ TO ‘‘@‘‘;
GRANT PROXY ON ‘developer‘@‘localhost‘ TO ‘‘@‘‘;

用户登录:

mysql --user=myuser --password=‘myuser_pass‘ ...

服务找不到myuser这个用户,但是能匹配上’’@’’然后服务调用ldap_auth,使用myuser和myuser_pass作为用户名密码验证。

如果ldap_auth发现myuser_pass不是myuser的正确密码,连接失败。

如果连接成功,发现myuser是一个developer,那么就返回developer用户名给mysql服务,然后myuser使用developer的权限:

mysql> SELECT USER(), CURRENT_USER();
+------------------+---------------------+
| USER()           | CURRENT_USER()      |
+------------------+---------------------+
| myuser@localhost | developer@localhost |
+------------------+---------------------+

 

如果ldap_auth返回的是manager,则:

mysql> SELECT USER(), CURRENT_USER();
+------------------+-------------------+
| USER()           | CURRENT_USER()    |
+------------------+-------------------+
| myuser@localhost | manager@localhost |
+------------------+-------------------+

 

6.3.9.3 代理用户系统变量

主要有2个系统变量:

1.proxy_user:如果为null,表示没有启动代理,如果是以默认代理用户验证的

mysql> SELECT @@proxy_user;
+--------------+
| @@proxy_user |
+--------------+
| ‘‘@‘‘        |
+--------------+

2.external_user:在验证过程中被使用到,会作为插件的设置被用户验证客户端。

6.3.10 使用SSL加密连接

mysql的标准配置是尽量加快传输,所以连接是不加密的。

6.3.10.1 基本SSL概念

手册:

 

6.3.10.2 为mysql配置SSL

1.如果不是支持SSL的bianry 版本,就下载安装OpenSSL

2. 如果不是支持SSL的bianry 版本,配置编译选项

shell> cmake . -DWITH_SSL=bundled

如果使用yassl,配置如下:

shell> cmake . -DWITH_SSL=system

然后编译安装

3.检查是否支持SSL

mysql> SHOW VARIABLES LIKE ‘have_ssl‘;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_ssl      | YES   |
+---------------+-------+

6.3.9.10.3 使用SSL连接

使用ssl连接需要配置一下几个选项:

Name

Cmd-Line

Option file

System Var

Status Var

Var Scope

Dynamic

 

 

Yes

 

Global

No

 

 

Yes

 

Global

No

Yes

Yes

 

 

 

 

Yes

Yes

 

 

 

 

Yes

Yes

 

 

Global

No

Variable

 

 

Yes

 

Global

No

Yes

Yes

 

 

Global

No

Variable

 

 

Yes

 

Global

No

Yes

Yes

 

 

Global

No

Variable

 

 

Yes

 

Global

No

Yes

Yes

 

 

Global

No

Variable

 

 

Yes

 

Global

No

Yes

Yes

 

 

Global

No

Variable

 

 

Yes

 

Global

No

Yes

Yes

 

 

Global

No

Variable

 

 

Yes

 

Global

No

Yes

Yes

 

 

Global

No

Variable

 

 

Yes

 

Global

No

Yes

Yes

 

 

 

 

6.3.10.5 为mysql生成证书和公钥私钥

具体看:

6.3.11  从windows使用ssh链接到mysql

具体看:

6.3.12 Mysql企业版审计日志插件

审计日志插件名叫audit_log,当安装了插件后,MySQL服务会产生日志文件包括服务的活动审计记录。

安装了插件之后会写入到审计日志,日志路径由变量audit_log_file控制,默认为audit.log。

审计日志的格式为XML格式,在服务启动的时候,可以通过audit_log_format控制系统变量,设置日志格式。

由audit_log_policy控制审计的事件,默认为all,可以设置为LOGINS,QUERIES,NONE。

 

把日志记录格式从老的改成新的需要以下步骤:

1.停止服务

2.重命名审计日志文件

3.使用新的audit_log_format重启服务

6.3.12.1 安装审计插件

使用配置文件,或者命令行参数plugin-load设置:

[mysqld]
plugin-load=audit_log.so

或者使用install plugin加载

mysql> INSTALL PLUGIN audit_log SONAME ‘audit_log.so‘;

使用了install plugin之后,下次启动会自动加载

使用audit-log配置文件,来强制插件初始化,否则服务启动报错。

6.3.12.2 审计日志安全性考虑

审计日志不加密,为了考虑到敏感信息安全性问题,考虑放在只能管理员和mysql启动用户访问。

6.3.12.3 审计日志

具体看:

6.3.12.4 审计日志记录控制

当audit_log_rotate_on_size大于0,写入后文件的大小大于audit_log_rotate_on_size,服务会重命名审计日志,打开一个新的审计日志。

6.3.12.5 审计日志插件选项和变量

具体看:

6.3.13 SQL-Based MySQL账号活动审计

具体看:

 

[MySQL Reference Manual] 6 安全性,布布扣,bubuko.com

热门排行

今日推荐

热门手游