Mysql安全配置

wyzsk發表於2020-08-19

相關學習資料

http://drops.wooyun.org/tips/2245
http://www.cnblogs.com/siqi/archive/2012/11/21/2780966.html
http://hi.baidu.com/liveinyc/item/08d5e71cfb2872416926bb84
http://blog.chinaunix.net/uid-16728139-id-3683449.html
http://linux.chinaunix.net/techdoc/database/2008/01/14/976546.shtml
http://www.cnblogs.com/yuwensong/archive/2013/03/26/2981965.html
http://hi.baidu.com/xmflycat/item/7567e3c37c43ba57bcef6951
http://www.jb51.net/article/30319.htm
http://hi.baidu.com/schyman/item/cd0884f5cb85af49922af2b8

 

目錄

1. 前言
2. Mysql賬戶許可權安全
3. Mysql資料的網路安全配置
4. 密碼策略安全
5. Mysql日誌
6. Mysql資料庫服務所在主機安全配置
7. 部署SQL隱碼攻擊檢測、防禦模組
8. mysqld安全相關啟動選項
9. mysql備份策略

 

1. 前言

Mysql資料庫安全配置、或者叫加固屬於風險模型中的一環,它需要安全人員在理論和實踐的學習中不斷髮現新的問題,並針對這些問題對資料的各個方面的配置進行強化。本文試圖圍繞著資料庫風險識別、資料庫安全加固這個問題,探討可以採取的措施來最大程度的保證我們的資料庫的安全控制處在一個較好的水平。 

 

2. Mysql賬戶許可權安全

mysql中存在4個控制許可權的表,分別為

1. mysql.USER表
2. mysql.DB表
3. mysql.TABLES_PRIV表
4. mysql.COLUMNS_PRIV表

要注意的是,Mysql中有一個資料庫"information_schema",似乎裡面儲存的也是一些許可權資訊,但是要明白的是,這個資料庫"information_schema"是為系統管理員提供後設資料的一個簡便方式,它實際上是一個檢視,可以理解為對Mysql中的一個資訊的封裝,對於Mysql主程式來說,身份認證和授權的資訊的來源只有一個,就是"mysql"。

http://www.cnblogs.com/hzhida/archive/2012/08/08/2628826.html

1. mysql.USER表

select * from USER;
desc USER;
mysql> desc USER;
+------------------------+-----------------------------------+------+-----+---------+-------+
| Field                  | Type                              | Null | Key | Default | Extra |
+------------------------+-----------------------------------+------+-----+---------+-------+
| Host                   | char(60)                          | NO   | PRI |         |       |
| User                   | char(16)                          | NO   | PRI |         |       |
| Password               | char(41)                          | NO   |     |         |       |
| Select_priv            | enum('N','Y')                     | NO   |     | N       |       |
| Insert_priv            | enum('N','Y')                     | NO   |     | N       |       |
| Update_priv            | enum('N','Y')                     | NO   |     | N       |       |
| Delete_priv            | enum('N','Y')                     | NO   |     | N       |       |
| Create_priv            | enum('N','Y')                     | NO   |     | N       |       |
| Drop_priv              | enum('N','Y')                     | NO   |     | N       |       |
| Reload_priv            | enum('N','Y')                     | NO   |     | N       |       |
| Shutdown_priv          | enum('N','Y')                     | NO   |     | N       |       |
| Process_priv           | enum('N','Y')                     | NO   |     | N       |       |
| File_priv              | enum('N','Y')                     | NO   |     | N       |       |
| Grant_priv             | enum('N','Y')                     | NO   |     | N       |       |
| References_priv        | enum('N','Y')                     | NO   |     | N       |       |
| Index_priv             | enum('N','Y')                     | NO   |     | N       |       |
| Alter_priv             | enum('N','Y')                     | NO   |     | N       |       |
| Show_db_priv           | enum('N','Y')                     | NO   |     | N       |       |
| Super_priv             | enum('N','Y')                     | NO   |     | N       |       |
| Create_tmp_table_priv  | enum('N','Y')                     | NO   |     | N       |       |
| Lock_tables_priv       | enum('N','Y')                     | NO   |     | N       |       |
| Execute_priv           | enum('N','Y')                     | NO   |     | N       |       |
| Repl_slave_priv        | enum('N','Y')                     | NO   |     | N       |       |
| Repl_client_priv       | enum('N','Y')                     | NO   |     | N       |       |
| Create_view_priv       | enum('N','Y')                     | NO   |     | N       |       |
| Show_view_priv         | enum('N','Y')                     | NO   |     | N       |       |
| Create_routine_priv    | enum('N','Y')                     | NO   |     | N       |       |
| Alter_routine_priv     | enum('N','Y')                     | NO   |     | N       |       |
| Create_user_priv       | enum('N','Y')                     | NO   |     | N       |       |
| Event_priv             | enum('N','Y')                     | NO   |     | N       |       |
| Trigger_priv           | enum('N','Y')                     | NO   |     | N       |       |
| Create_tablespace_priv | enum('N','Y')                     | NO   |     | N       |       |
| ssl_type               | enum('','ANY','X509','SPECIFIED') | NO   |     |         |       |
| ssl_cipher             | blob                              | NO   |     | NULL    |       |
| x509_issuer            | blob                              | NO   |     | NULL    |       |
| x509_subject           | blob                              | NO   |     | NULL    |       |
| max_questions          | int(11) unsigned                  | NO   |     | 0       |       |
| max_updates            | int(11) unsigned                  | NO   |     | 0       |       |
| max_connections        | int(11) unsigned                  | NO   |     | 0       |       |
| max_user_connections   | int(11) unsigned                  | NO   |     | 0       |       |
| plugin                 | char(64)                          | YES  |     |         |       |
| authentication_string  | text                              | YES  |     | NULL    |       |
| password_expired       | enum('N','Y')                     | NO   |     | N       |       |
+------------------------+-----------------------------------+------+-----+---------+-------+

2. mysql.DB表

select * from DB;
desc DB;
mysql> desc DB; +-----------------------+---------------+------+-----+---------+-------+
| Field                 | Type          | Null | Key | Default | Extra |
+-----------------------+---------------+------+-----+---------+-------+
| Host                  | char(60)      | NO   | PRI |         |       |
| Db                    | char(64)      | NO   | PRI |         |       |
| User                  | char(16)      | NO   | PRI |         |       |
| Select_priv           | enum('N','Y') | NO   |     | N       |       |
| Insert_priv           | enum('N','Y') | NO   |     | N       |       |
| Update_priv           | enum('N','Y') | NO   |     | N       |       |
| Delete_priv           | enum('N','Y') | NO   |     | N       |       |
| Create_priv           | enum('N','Y') | NO   |     | N       |       |
| Drop_priv             | enum('N','Y') | NO   |     | N       |       |
| Grant_priv            | enum('N','Y') | NO   |     | N       |       |
| References_priv       | enum('N','Y') | NO   |     | N       |       |
| Index_priv            | enum('N','Y') | NO   |     | N       |       |
| Alter_priv            | enum('N','Y') | NO   |     | N       |       |
| Create_tmp_table_priv | enum('N','Y') | NO   |     | N       |       |
| Lock_tables_priv      | enum('N','Y') | NO   |     | N       |       |
| Create_view_priv      | enum('N','Y') | NO   |     | N       |       |
| Show_view_priv        | enum('N','Y') | NO   |     | N       |       |
| Create_routine_priv   | enum('N','Y') | NO   |     | N       |       |
| Alter_routine_priv    | enum('N','Y') | NO   |     | N       |       |
| Execute_priv          | enum('N','Y') | NO   |     | N       |       |
| Event_priv            | enum('N','Y') | NO   |     | N       |       |
| Trigger_priv          | enum('N','Y') | NO   |     | N       |       |
+-----------------------+---------------+------+-----+---------+-------+

3. mysql.TABLES_PRIV表

select * from TABLES_PRIV;
desc TABLES_PRIV;
mysql> desc TABLES_PRIV;  
+-------------+-----------------------------------------------------------------------------------------------------------------------------------+------+-----+-------------------+-----------------------------+
| Field       | Type                                                                                                                              | Null | Key | Default           | Extra                       |
+-------------+-----------------------------------------------------------------------------------------------------------------------------------+------+-----+-------------------+-----------------------------+
| Host        | char(60)                                                                                                                          | NO   | PRI |                   |                             |
| Db          | char(64)                                                                                                                          | NO   | PRI |                   |                             |
| User        | char(16)                                                                                                                          | NO   | PRI |                   |                             |
| Table_name  | char(64)                                                                                                                          | NO   | PRI |                   |                             |
| Grantor     | char(77)                                                                                                                          | NO   | MUL |                   |                             |
| Timestamp   | timestamp                                                                                                                         | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| Table_priv  | set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') | NO   |     |                   |                             |
| Column_priv | set('Select','Insert','Update','References')                                                                                      | NO   |     |                   |                             |
+-------------+-----------------------------------------------------------------------------------------------------------------------------------+------+-----+-------------------+-----------------------------+

4. mysql.COLUMNS_PRIV表

select * from COLUMNS_PRIV;
desc COLUMNS_PRIV;
mysql> desc COLUMNS_PRIV;  +-------------+----------------------------------------------+------+-----+-------------------+-----------------------------+
| Field       | Type                                         | Null | Key | Default           | Extra                       |
+-------------+----------------------------------------------+------+-----+-------------------+-----------------------------+
| Host        | char(60)                                     | NO   | PRI |                   |                             |
| Db          | char(64)                                     | NO   | PRI |                   |                             |
| User        | char(16)                                     | NO   | PRI |                   |                             |
| Table_name  | char(64)                                     | NO   | PRI |                   |                             |
| Column_name | char(64)                                     | NO   | PRI |                   |                             |
| Timestamp   | timestamp                                    | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| Column_priv | set('Select','Insert','Update','References') | NO   |     |                   |                             |
+-------------+----------------------------------------------+------+-----+-------------------+-----------------------------+

以上是這4個表的基本結構,在我們進行資料庫連線、登入的時候,mysql許可權表的驗證過程為:

1. 先從user表中的:
    1) Host
    2) User
    3) Password
這3個欄位中判斷連線的ip、使用者名稱、密碼是否存在,存在則通過驗證。
2. 通過身份認證後,進行許可權分配,按照:
    1) user
    2) db
    3) tables_priv
    4) columns_priv
的順序進行驗證。
即先檢查全域性許可權表user,如果user中對應的許可權為Y,則此使用者對所有資料庫的許可權都為Y,將不再檢查db,tables_priv,columns_priv
如果全域性許可權表user對應的許可權為N,則到db表中檢查此使用者對應的具體資料庫,並得到db中為Y的許可權
如果db中為N,則檢查tables_priv中此資料庫對應的具體表,取得表中的許可權Y,以此類推。逐級下降

用流程圖表示如下:

瞭解了Mysql的賬戶許可權原理和判斷流程,我們接下來需要了解就是應該以怎樣的方式去進行許可權配置,才能達到所謂的"最小許可權原則"呢?Mysql的賬戶許可權優先順序順序是:

user->db->tables_priv->columns_pri

稍作思考,我們可以發現,這些表的作用本質上是一樣的,區別就在於它們的作用域範圍不同,從user到columns_pri逐級作用域範圍降低,因此控制粒度也增大,它們的配置遵循"就近原則",即以優先順序最低的那個為準,所以,我們在進行Mysql的賬戶許可權安全配置的時候會發現"我們似乎在做很多重複性的工作"。但我們要明白的,Mysql的這種逐層次的許可權配置體系為我們提供了一個細粒度的控制方法。所以我們的許可權配置也應該按照這個順序來有規劃地進行。

1. USER表

許可權

許可權級別

許可權說明

最佳安全實踐: 網站使用賬戶是否給予

CREATE

  資料庫、表或索引

建立資料庫、表或索引許可權

建議給與,安裝WEB系統時需要建立表

DROP

  資料庫或表

刪除資料庫或表許可權

        建議給與

GRANT OPTION

資料庫、表或儲存的程式

賦予許可權選項

        不建議給與

REFERENCES

  資料庫或表

        不建議給與

ALTER

    表

更改表,比如新增欄位、索引等

        建議給與

DELETE

    表

刪除資料許可權

        建議給與

INDEX

    表

索引許可權

        建議給與

INSERT

    表

插入許可權

        建議給與

SELECT

    表

查詢許可權

        建議給與

UPDATE

    表

更新許可權

        建議給與

CREATE VIEW

    檢視

建立檢視許可權

        建議給與

SHOW VIEW

    檢視

檢視檢視許可權

        建議給與

ALTER ROUTINE

   儲存過程

更改儲存過程許可權

        不建議給與

CREATE ROUTINE

   儲存過程

建立儲存過程許可權

        不建議給與

EXECUTE

   儲存過程

執行儲存過程許可權

        不建議給與

FILE

伺服器主機上的檔案訪問

檔案訪問許可權

不建議給與,防止因為注入導致的隱私檔案洩漏

CREATE TEMPORARY TABLES

   伺服器管理

建立臨時表許可權

不建議給與,防止藉助臨時表發動的二次注入

LOCK TABLES

   伺服器管理

鎖表許可權

       不建議給與

CREATE USER

   伺服器管理

建立使用者許可權

         不建議給與

PROCESS

   伺服器管理

檢視程式許可權

       不建議給與

RELOAD

   伺服器管理

執行flush-hosts, flush-logs, flush-privileges, flush-status, flush-tables, flush-threads, refresh, reload等命令的許可權

        不建議給與

REPLICATION CLIENT

   伺服器管理

複製許可權

       不建議給與

REPLICATION SLAVE

     伺服器管理

複製許可權

       不建議給與

SHOW DATABASES

     伺服器管理

檢視資料庫列表許可權

       不建議給與

SHUTDOWN

   伺服器管理

關閉資料庫許可權

       不建議給與

SUPER

   伺服器管理

執行kill執行緒許可權

       不建議給與

從表格中可以看到,USER表主要針對資料庫的賬戶進行粗粒度的許可權控制,定義了"某人允許做什麼事"。

2. DB表

許可權

說明

網站使用賬戶是否給予

Select   

可對其下所有表進行查詢

建議給予

Insert            

可對其下所有表進行插入

建議給予

Update               

可對其下所有表進行更新

建議給予

Delete                   

可對其下所有表進行刪除

建議給予

Create                  

可在此資料庫下建立表或者索引

建議給予

Drop                 

可刪除此資料庫,及此資料庫下的表

不建議給予

Grant               

賦予許可權選項

不建議給予

References             

未來MySQL特性的佔位符

不建議給予

Index                

可對其下的所有表進行索引

建議給予

Alter                  

可對其下的所有表進行更改

建議給予

Create_tmp_table          

建立臨時表

不建議給予

Lock_tables             

可對其下所有表進行鎖定

不建議給予

Create_view              

可在此資料下建立檢視

建議給予

Show_view             

可在此資料下檢視檢視

建議給予

Create_routine         

可在此資料下建立儲存過程

不建議給予

Alter_routine        

可在此資料下更改儲存過程

不建議給予

Execute         

可在此資料下執行儲存過程

不建議給予

Event               

可在此資料下建立事件排程器

不建議給予

Trigger

可在此資料下建立觸發器

不建議給予

DB表可以看成是USER表對許可權控制的一個補充,一個更細粒度地、針對資料庫庫級別的許可權控制。

同時,DB表也隱式包含了將賬戶限定在某個資料庫的範圍內這個配置,即限制某個使用者只能用對它自己的資料庫的控制權,對不屬於它的資料庫禁止操作,這能有效防止橫向越權的發生。

mysql> select host,db,user from db;
+------+---------+------+
| host | db      | user |
+------+---------+------+
| %    | test    |      |
| %    | test\_% |      |
+------+---------+------+

可以看到,user欄位為空,表示當前不對使用者做任何資料庫屬許可權制,在網站的部署過程中,應該單獨針對網站建立一個賬戶一個獨立的資料庫,併為這個賬戶分配唯一的專屬資料庫,防止網路被入侵後的橫向、縱向提權。

對於Mysql中的賬戶許可權相關的安全配置,總結如下:

1. 針對每個網站建立一個單獨的賬戶
2. 為每個網站單獨建立一個專屬資料庫(雖然DEDE、DZ普通採用表字首的方法來實現"一庫多站",但好的做法還是"一庫一站") 
3. 按照user->db->tables_priv->columns_pri的順序進行細粒度的許可權控制
4. 為每個使用者單獨配置一個專屬資料庫,保證當前使用者的所有操作只能發生在它自己的資料庫中,防止SQL隱碼攻擊發生後,黑客通過注入點訪問到系統表

賬戶許可權安全配置需要的常用命令 

1. 新建一個使用者並給予相應資料庫的許可權
grant select,insert,update,delete,create,drop privileges on database.* to user@localhost identified by 'passwd';
grant all privileges on database.* to user@localhost identified by 'passwd';

2. 重新整理許可權
flush privileges;

3. 顯示授權
show grants;

4. 移除授權
revoke delete on *.* from 'user'@'localhost';

5. 刪除使用者
drop user 'user'@'localhost';

6. 給使用者改名
rename user 'jack'@'%' to 'jim'@'%';

7. 給使用者改密碼
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456');

 

3. Mysql資料的網路安全配置

對資料庫所在的DMZ的網路拓樸的安全配置也是我們在進行安全評估的時候需要考慮的一個方面,這對防禦內網掃描、網路攻擊有一定幫助。

0x1: 限制訪問Mysql埠的IP
對Mysql的訪問IP的限制,可以從應用層和主機層來分別達到目的

1. 主機層:
    1) windows可以通過windows防火牆
    2) Linux下可以通過iptables
來限制允許訪問mysql埠的IP地址
//只允許指定的IP進行訪問
iptables -A INPUT -p tcp -s xxxx.xxxx.xxxx.xxxx/24 --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp -s xxxx.xxxx.xxxx.xxxx/24 --dport 3306 -j ACCEPT
..
iptables -P INPUT DROP

可以看到,這種方法的缺點是硬編碼導致靈活性低,如果mysql的預設埠3306被修改了(例如8890),則這條iptables規則也需要相應的修改

2. 應用層
所謂應用層的IP限制訪問,是Mysql自身提供的訪問控制機制,能夠針對訪問者的IP地址進行訪問控制。在user、db、tables_priv、columns_priv中的HOST欄位裡記錄的IP地址,例如:
mysql> select host,user,password from user;
+-----------+------+-------------------------------------------+
| host      | user | password                                  |
+-----------+------+-------------------------------------------+
| localhost | root | *832EB84CB764129D05D498ED9CA7E5CE9B8F83EB |
| 127.0.0.1 | root | *832EB84CB764129D05D498ED9CA7E5CE9B8F83EB |
| ::1       | root | *832EB84CB764129D05D498ED9CA7E5CE9B8F83EB |
| localhost |      |                                           |
+-----------+------+-------------------------------------------+

這幾行記錄表明了root這個賬戶只能是本機登入,在部署的過程中,我們可以為指定賬戶新增某個安全的跳板機,並保證這個跳板機IP是不變的。

0x2: 修改mysql的埠
windows下可以修改配置檔案my.ini來實現,linux可以修改配置檔案my.cnf來實現。

port     = 3306

對mysql埠的修改可以從一定程度上防止埠掃描工具的掃描。

0x3: 限制連線使用者的數量
資料庫的某使用者多次遠端連線,會導致效能的下降和影響其他使用者的操作,有必要對其進行限制。可以通過限制單個賬戶允許的連線數量來實現,設定my.cnf 檔案的mysqld中的max_user_connections變數來完成。GRANT語句也可以支援資源控制選項來限制伺服器對一個賬戶允許的使用範圍。

#vi /etc/my.cnf
[mysqld]
max_user_connections 2

 

4. 密碼策略安全

這裡所謂的密文策略安全包括Mysql自身的賬戶密碼的安全、也包括網站使用者的密碼安全。

0x1: mysql賬戶密碼

因為mysql本身沒有抗窮舉的帳號鎖定機制,所以對於mysql自身的登入帳號,尤其是root帳號,需要遵循"密碼強度策略"設定高強度的密碼,保證攻擊者從窮舉帳號攻擊這條路無法獲得合適的投資收益比。

0x2: 網站使用者的密碼

資料庫管理員無法規定使用者的網站使用什麼樣的密碼策略,這完全取決於使用者自己的編碼習慣、或者說是站長所使用的CMS的編碼習慣。這方面,mysql無法做的更多,但也許可以做的是建立一個針對網站密碼窮舉、脫庫攻擊的日誌追溯系統,當發生脫庫攻擊時能第一時間給使用者提供"事發現場"的更多資訊。或者資料庫管理員主動進行可控的撞庫測試,提前幫助使用者發生潛在的撞庫、脫庫風險。

 

5. Mysql日誌

啟動Mysql的日誌不僅可以為我們提供效能熱點的分析,還可以幫助我們加固Mysql資料庫的安全,例如:

1. 從日誌中獲得典型SQL隱碼攻擊語句
2. 利用正則模型從日誌中捕獲注入攻擊的發生
3. 在脫庫、資料洩漏之後獲得關於受攻擊資料庫的情況、洩漏範圍等資料

mysql有以下幾種日誌,它們都在my.ini中進行配置:

1. 錯誤日誌:-log-err
log-error=E:/wamp/logs/mysql_error.log

2. 查詢日誌(記錄所有SQL語句):-log 
log=E:/wamp/logs/mysql.log

3. 慢查詢日誌:-log-slow-queries 
    1) 檢視慢查詢時間
    show variables like "long_query_time";預設10s
    2) 檢視慢查詢配置情況
    show status like "%slow_queries%";
    3) 檢視慢查詢日誌路徑
    show variables like "%slow%";
//儲存位置、長SQL的閾值
E:\wamp\bin\mysql\mysql5.6.12\data\LittleHann-PC-slow.log
long_query_time=5

4. 更新日誌:-log-update 

5. 二進位制日誌:-log-bin
//記錄除select語句之外的所有sql語句到日誌中,可以用來恢復資料檔案
log-bin=E:/wamp/logs/bin

檢視日誌開啟情況:

show variables like 'log_%'; 
+----------------------------------------+----------------------------------------------------+
| Variable_name                          | Value                                              |
+----------------------------------------+----------------------------------------------------+
| log_bin                                | ON                                                 |
| log_bin_basename                       | E:\wamp\bin\mysql\mysql5.6.12\data\mysql-bin       |
| log_bin_index                          | E:\wamp\bin\mysql\mysql5.6.12\data\mysql-bin.index |
| log_bin_trust_function_creators        | OFF                                                |
| log_bin_use_v1_row_events              | OFF                                                |
| log_error                              | E:\wamp\logs\mysql.log                             |
| log_output                             | FILE                                               |
| log_queries_not_using_indexes          | OFF                                                |
| log_slave_updates                      | OFF                                                |
| log_slow_admin_statements              | OFF                                                |
| log_slow_slave_statements              | OFF                                                |
| log_throttle_queries_not_using_indexes | 0                                                  |
| log_warnings                           | 1                                                  |
+----------------------------------------+----------------------------------------------------+

 

6. Mysql資料庫服務所在主機安全配置

安全問題是一個綜合的縱深問題,Mysql的安全配置和所在系統(*iux、windows)的安全配置密切相關。

0x1: mysql程式執行賬號
所謂"mysql程式執行賬戶",即以什麼樣的身份許可權來啟動mysqld這個服務程式的。對於作業系統來說,每一個程式都有一個對應的"程式執行帳號",這個程式執行帳號決定了這個應用程式可以獲得哪些作業系統的許可權。

1. 在windows下禁止使用local system(nt authority\system)來執行mysql賬戶,可以考慮使用network service或者自己新建一個windows賬號,但是必須給與mysql程式所在目錄的讀取許可權和data目錄的讀取和寫入許可權
2. 在linux下,新建一個mysql賬號,並在安裝的時候就指定mysql以mysql賬戶來執行,給與程式所在目錄的讀取許可權,data所在目錄的讀取和寫入許可權。

0x2: mysql執行賬號的磁碟許可權
對mysql執行帳號的磁碟許可權的配置,就是在進行ACL的配置(資料夾右鍵->屬性->安全),對於ACL的配置,我們需要牢記的是"預設禁止原則",即作業系統會預設對沒有明確指示的許可權設定為禁止,即假如你給一個使用者授予了某個資料夾的讀許可權,那麼它只有讀許可權,而不會擁有寫許可權(許可權繼承不考慮在內)。
對於mysql執行張厚啊的磁碟ACL配置,我們可以遵循以下原則

1. mysql執行賬號需要給予程式所在目錄的讀取許可權,以及data目錄的讀取和寫入許可權,保證mysql的正常執行
2. 不容許給予其他目錄的寫入和執行許可權,特別是有網站的,這可以有效防禦針對mysql的提權、或者webshell提權
    1) udf提權
    2) 系統關鍵目錄、登錄檔寫入啟動檔案 
3. 取消mysql執行賬戶對於cmd,sh等一些程式的執行許可權,這可以防禦當mysql核心帳號被黑客獲取後進一步提權
    1) root賬戶被洩露
    由於對cmd、sh等關鍵程式進行了許可權控制,黑客無法繼續深入作業系統提權

0x3: Chrooting
Chroot是Unix/類Unix的一種手段,它的建立會將其與主系統幾乎完全隔離,也就是說,一旦遭到什麼問題,也不會危及到正在執行的主系統。這是一個非常有效的辦法,特別是在配置網路服務程式的時候。

0x4: 刪除歷史命令記錄
歷史命令記錄是一種測通道資料洩漏,從某種程式上來說,"歷史命令記錄"就像種植在系統上的一個鍵盤記錄rootkit,如果黑客獲取到了目標伺服器的webshell,就可以通過閱讀"歷史命令記錄"來獲取到大量的管理員操作記錄,包括帳號和密碼。
這些歷史檔案包括:

1. ~/.bash_history
2. ~/.mysql_history 
.. 
cat /dev/null > ~/.bash_history
cat /dev/null > ~/.mysql_history

0x5: mysql.sock安全配置
預設情況下,PHP支援使用socket方式和msyql資料庫進行通訊,換句話來說,這也意味著,在伺服器本機可以允許無密碼直接登入mysql,請看下面的一段例項程式碼:

<?php
        ini_set("mysql.default_socket = /var/lib/mysql/mysql.sock"); 

        $sql = "select user();";
        $res = mysql_query($sql);
        $final = mysql_fetch_array($res);
        die(var_dump($final)); 
?>

執行成功,result:

array(2) { [0]=> string(16) "apache@localhost" ["user()"]=> string(16) "apache@localhost" }

這意味著黑客在獲取了目標伺服器的webshell之後,可以在不知道mysql帳號密碼的情況下直接從資料庫中獲取隱私資料。

防禦的方法還是一樣,針對mysql程式帳號進行磁碟ACL控制,防止mysql越權讀/寫/執行非mysql目錄下的檔案。

 

7. 部署SQL隱碼攻擊檢測、防禦模組

根據OWASP2013的報告顯示,針對資料庫的攻擊方式,SQL隱碼攻擊依然是主要的因素,因此針對SQL Injection的攻擊,除了針對應用層的程式碼安全審計、SDLC之外,在資料庫層部署資料庫防火牆也應該作為縱深防禦的一個手段。

目前基於SQL隱碼攻擊檢測、防禦的的資料庫防火牆大概有以下幾個:

1. 安華金和資料庫防火牆系統(Xsecure-DBFirewall)
http://www.schina.cn/a/fangan/shujufangxielou/17.html
2. Snort入侵檢測系統
能針對指定埠進行正則特徵匹配方式的SQL隱碼攻擊檢測
http://www.snort.org/
3. Java/J2EE 過濾器
對於J2ee的WEB應用來說,可以在HTTP請求上部署過濾器,並將SQL隱碼攻擊檢測規律寫在過濾器中
4. druid-sql-wall開源SQL檢測、阻斷系統
https://github.com/alibaba/druid
5. D盾
6. 安全狗 

 

8. mysqld安全相關啟動選項

1. –local-infile[={0|1}]
如果用–local-infile=0啟動伺服器,則客戶端不能使用LOCAL in LOAD DATA語句,防止基於注入的直接檔案讀取資料洩漏

2. –old-passwords
強制伺服器為新密碼生成短(pre-4.1)密碼雜湊。當伺服器必須支援舊版本客戶端程式時,為了保證相容性這很有用。

3. (OBSOLETE) –safe-show-database
    1) 在MySQL 5.1以前版本的MySQL中,該選項使SHOW DATABASES語句只顯示使用者具有部分許可權的資料庫名
    2) 在MySQL 5.1中,該選項不再作為現在的 預設行為使用,有一個SHOW DATABASES許可權可以用來控制每個賬戶對資料庫名的訪問。

4. –safe-user-create
如果啟用,使用者不能用GRANT語句建立新使用者,除非使用者有mysql.user表的INSERT許可權。如果你想讓使用者具有授權許可權來建立新使用者,你應給使用者授予下面的許可權:
mysql> GRANT INSERT(user) ON mysql.user TO 'user_name'@'host_name’;
這樣確保使用者不能直接更改許可權列,必須使用GRANT語句給其它使用者授予該許可權。

5. –secure-auth
不允許鑑定有舊(pre-4.1)密碼的賬戶。

6. --skip-grant-tables
這個選項導致伺服器根本不使用許可權系統。這給每個人以完全訪問所有的資料庫的權力,這個選項常常在發生了忘記了msyql密碼的情況使用這個方式在本機"無密碼登入mysql"
通過執行mysqladmin flush-privileges或mysqladmin eload命令,或執行FLUSH PRIVILEGES語句,你能告訴一個正在執行的伺服器再次開始使用授權表。

7. --skip-name-resolve
主機名不被解析。所有在授權表的Host的列值必須是IP號或localhost

8. --skip-networking
在網路上不允許TCP/IP連線。所有到mysqld的連線必須經由Unix套接字進行

9. -skip-show-database
使用該選項,只允許有SHOW DATABASES許可權的使用者執行SHOW DATABASES語句,該語句顯示所有資料庫名。不使用該選項,允許所有使用者執行SHOW DATABASES,但只顯示使用者有SHOW DATABASES許可權或部分資料庫許可權的資料庫名。請注意全域性許可權指資料庫的許可權。

 

9. mysql備份策略

像mysql、sqlserver、access這種資料庫都是將資料以單獨檔案的形式儲存在磁碟上的,所以,對於資料庫的備份也可以採用傳統的檔案備份策略。總的來說,有以下方式:

1. 本地備份
使用mysqldump進行備份非常簡單,在備份資料庫的時候,我們還可以同時使用管道gzip命令對備份檔案進行壓縮,可以採用Rsync的異地備份方式方式,將備份伺服器的目錄掛載到資料庫伺服器,將資料庫檔案備份打包後,通過crontab定時備份資料:
備份資料使用命令:
#!/bin/sh
time=`date +"("%F")"%R`
$/usr/local/mysql/bin/mysqldump -u root -p111 database_backup | gzip > /home/zhenghan/mysql/mysql_backup.$time.gz
# crontab -l
# m h  dom mon dow   command
00 00 * * * /home/zhenghan/mysql/backup.sh
恢復資料使用命令:
gzip -d mysql_backup.\(2014-06-17\)00\:00.gz
mysql_backup.(2014-06-17)00:00
#mysql –u root -p111 < /home/zhenghan/mysql/mysql_backup.\(2014-06-17\)00\:00

2. 網路備份

3. MySQL本身自帶的mysqldump備份
使用mysqldump可以把整個資料庫裝載到一個單獨的文字檔案中。這個檔案包含有所有重建您的資料庫所需要的SQL命令。這個命令取得所有的模式(schema)並且將其轉換成DDL語法(CREATE語句,即資料庫定義語句),取得所有的資料,並且從這些資料中建立INSERT語句。這個工具將您的資料庫中所有的設計倒轉。因為所有的東西都被包含到了一個文字檔案中。這個文字檔案可以用一個簡單的批處理和一個合適SQL語句導回到MySQL中。

4. 直接複製資料庫檔案的備份形式
直接拷貝資料檔案最為直接、快速、方便,但缺點是基本上不能實現增量備份。為了保證資料的一致性,需要在備份檔案前,執行以下SQL語句:FLUSH TABLES WITH READ LOCK;也就是把記憶體中的資料都重新整理到磁碟中,同時鎖定資料表,以保證拷貝過程中不會有新的資料寫入。這種方法備份出來的資料恢復也很簡單,直接拷貝回原來的資料庫目錄下即可。

 

Copyright (c) 2014 LittleHann All rights reserved