一、說明
本篇文章主要說一說MySQL中通路控制控制點的相關内容和了解。
二、測評項
a)應對登入的使用者配置設定賬戶和權限;
b)應重命名或删除預設賬戶,修改預設賬戶的預設密碼;
c)應及時删除或停用多餘的、過期的賬戶,避免共享賬戶的存在;
d)應授予管理使用者所需的最小權限,實作管理使用者的權限分離;
e)應由授權主體配置通路控制政策,通路控制政策規定主體對客體的通路規則;f)通路控制的粒度應達到主體為使用者級或程序級,客體為檔案、資料庫表級;
g)應對重要主體和客體設定安全标記,并控制主體對有安全标記資訊資源的通路。
三、測評項a
a)應對登入的使用者配置設定賬戶和權限;
3.1. 要求1
如果從字面意思來看,就是一個廢話,使用者都登入賬戶了,自然就存在着賬戶。
這裡的意思是應該是你本來就存在“多個賬戶”,然後當使用者使用時要适當的“配置設定賬戶”給使用者,而賬戶再擁有不一樣的權限,這樣就實作了将權限通過賬戶配置設定給使用者(自然人)。
是以,該測評項就需要MySQL中存在至少兩個賬戶,且這兩個賬戶的權限不一樣。
3.2. 要求2
在測評要求中測評實施如下:
在MySQL中,安裝完成後預設存在的賬戶一般有3個,都是root:
先不管其中是否存在多餘賬戶,這個賬戶如果使用的話一般當做超級管理者來用,預設狀況下root賬戶也擁有着所有的全局權限,也不需要對root賬戶的權限做什麼限制。
全局權限存儲在user表中,裡面有着權限列:
四、測評項b
b)應重命名或删除預設賬戶,修改預設賬戶的預設密碼;
預設賬戶root當然是可以修改使用者名的,但是一般資料庫和實際業務關聯比較深,修改資料庫使用者的使用者名肯定會影響到業務。
是以從實際角度來說,應該是建議修改root的使用者名,但不強制要求。
如果沒有修改使用者名或者禁用賬戶的話,似乎MySQL安裝好後root賬戶存在一個初始密碼(随機生成的)。
無論存不存在初始密碼,現在使用的密碼應該是強密碼,才符合測評要求。
五、測評項c
c)應及時删除或停用多餘的、過期的賬戶,避免共享賬戶的存在;
預設賬戶一般就是root賬戶,這裡個人覺得是存在多餘賬戶的:
在等保測評2.0:MySQL身份鑒别(上)中有說過:
對于MySQL來說,如上文所言,使用者的身份辨別為username + host,MySQL并沒有禁止出現完全一樣的username + host行,是以這裡是可能出現身份辨別不唯一的情況的。
這三個使用者的User都是root,雖然Host看上去不一樣,實際上也都是本機位址。
127.0.0.1就是本地的ip位址,localhost則是在hosts檔案裡(linux系統中)和ip位址進行了映射,其實映射的還是127.0.0.1位址,至于::1應該是ipv6格式的本機位址。
::1這個我不知道要如何才能連上,當使用者名為root的行隻剩下host值為::1的行的時候,使用使用者名root怎麼連都不可能連上。
對于127.0.0.1和localhost,在windows系統上沒啥差別,登入時其排序是不确定的(對于這種,應該是誰先建立誰在前)。
對于127.0.0.1和localhost,好像在linux上有一點差別:MySQL主機127.0.0.1與localhost差別總結
從正常的業務需求來說,明顯這三個使用者的身份辨別是不唯一的,應該删掉::1和另外一個。
至于非預設賬戶,可以通過訪談或者權限查詢來判斷是否為多餘賬戶。
六、測評項d
d)應授予管理使用者所需的最小權限,實作管理使用者的權限分離;
6.1. MySQL的權限結構
MySQL的權限是有多個層級的,分别是,存儲在各個表當中。
分别是:mysql.user表(全局權限)、mysql.db表(資料庫權限)、mysql.tables_priv(表權限)、mysql.columns_priv(列權限)。
權限判斷過程大概是這樣的:
用戶端操作核實階段,當用戶端的連接配接請求被MySQL伺服器端通過其身份認證後。那麼接下來就可以發送資料庫的操作指令給伺服器端處理,伺服器檢查使用者要執行的操作,在确認權限時,MySQL首先檢查user表,如果指定的權限沒有在user表中被授權;MySQL将檢查db表,db表時下一安全層級,其中的權限限定于資料庫層級,在該層級的SELECT權限允許使用者檢視指定資料庫的所有表中的資料;如果在該層級沒有找到限定的權限,則MySQL繼續檢查tables_priv表以及columns_priv表,如果所有權限表都檢查完畢,但還是沒有找到允許的權限操作,MySQL将傳回錯誤資訊,使用者請求的操作不能執行,操作失敗。其過程大概如下圖:
查詢某使用者的權限的話,可以去上述幾個權限表中檢視資料。
也可以使用show grants for 'xx'@'xx'語句,這個語句應該會把某使用者在這些表中的權限全部列出來:
+---------------------------------------------------------------------------------------------+
| Grants for dba@localhost |
+---------------------------------------------------------------------------------------------+
| GRANT RELOAD, SUPER, REPLICATION CLIENT ON *.* TO 'dba'@'localhost' |
| GRANT CREATE TEMPORARY TABLES ON `mysql`.* TO 'dba'@'localhost' |
| GRANT SELECT, INSERT, UPDATE, CREATE, DROP ON `mysql`.`backup_history` TO 'dba'@'localhost' |
| GRANT INSERT, UPDATE, CREATE, DROP ON `mysql`.`ibbackup_binlog_maker` TO 'dba'@'localhost' |
| GRANT INSERT, UPDATE, CREATE, DROP ON `mysql`.`backup_progress` TO 'dba'@'localhost' |
+---------------------------------------------------------------------------------------------+
其中第一行是全局權限,第二行是mysql資料庫的權限,第三、四行則是表一級的權限。
兩種查詢方法如下圖:
6.2. 測評項要求
那麼怎麼才算是符合呢?應該要根據應用程式業務複雜程度來判斷,應用程式業務越複雜或者越龐大,則資料庫賬戶的權限就應該劃分得越細緻。
反正,一個root賬戶從頭用到尾,那肯定是不符合的。
其餘的内容,可以參考下初級教程:
七、測評項e
e)應由授權主體配置通路控制政策,通路控制政策規定主體對客體的通路規則;
授權主體在資料庫中也就是擁有設定使用者權限的賬戶,也就是檢視user表、db表中的grant_priv字段。
賦予使用者權限的時候,加上With Grant Option,即該使用者則擁有了将獲得的權限再賦予其它人的權限(其實就是同時修改了grant_priv字段):
比如
mysql>grant all on *.* to test@’192.168.1.20’ identified by ‘123456’ WITH GRANT OPTION
mysql>flush privileges;
結果顯示:Grant_priv為"Y"
對于測評項而言,也就看資料庫内是否設定了此類賬戶,由此類賬戶(安全管理者)來制定通路控制政策。
八、測評項f
f)通路控制的粒度應達到主體為使用者級或程序級,客體為檔案、資料庫表級;
就是看權限控制粒度,對于客體,要看是否達到了資料庫表的級别,也即單獨對資料庫表設定權限(視圖、存儲過程也可以)。如果僅達到了資料庫級别或者伺服器級别的權限,那肯定是不符合要求的。
至于主體就不說了,MySQL中也沒存在使用者組。
九、測評項g
g)應對重要主體和客體設定安全标記,并控制主體對有安全标記資訊資源的通路。
MySQL自身應該不具備這個功能,可能要依靠作業系統或者第三方的什麼軟體來實作了。
關于安全标記,可以看看等保測評2.0:Windows通路控制中測評項g中的内容。
實際測評中,基本上就沒有能實作的,不過也不用太在意,因為這一個測評項不屬于高風險項。
等保2.0測評:MySQL安全審計
一、說明
本篇文章主要說一說MySQL資料庫安全審計控制點的相關内容和了解。
MySQL除了自身帶有的審計功能外,還存在着一些其它的審計插件。
雖然遇到這些插件的機率不高,我還是把這些插件的基本參數都列出來,到時候如果真遇到了,也不至于一頭霧水。
二、測評項
a)應啟用安全審計功能,審計覆寫到每個使用者,對重要的使用者行為和重要安全事件進行審計;
b)審計記錄應包括事件的日期和時間、使用者、事件類型、事件是否成功及其他與審計相關的資訊;
c)應對審計記錄進行保護,定期備份,避免受到未預期的删除、修改或覆寫等;
d)應對審計程序進行保護,防止未經授權的中斷。
三、測評項a
a)應啟用安全審計功能,審計覆寫到每個使用者,對重要的使用者行為和重要安全事件進行審計;
3.1. 自帶的審計功能
在MySQL中自帶了審計功能——general log,它會記錄所有關于mysql的sql語句(是以會給伺服器和資料庫帶來很大的資源占用)。
不過僅僅從測評要求的角度來說,如果開啟了general log,那麼是符合測評項a的。
查詢的時候,可以使用log或者general關鍵詞,這裡用的是general(不過用log要好一些):
show global variables like '%general%'
圖中的general_log變量的值為OFF,則表示沒有開啟。
general_log_file則表示日志存儲在哪,圖中是存儲在一個檔案中。
MySQL 5.1.6版開始,可以将日志存儲在表當中,這個由log_output參數進行控制,值為file,則代表存儲在檔案中,為table,則代表存儲在gengera_log表中。
mysql> show variables like 'log_output';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output | TABLE |
+---------------+-------+
mysql> select * from general_log;
| 2018-07-17 23:00:12 | root[root] @ localhost [] | 2 | 1132333306 | Query | select * from test.student3
也可以去看一看/etc/my.cnf檔案,檢視是否啟用了general_log:
[mysqld]
general_log = on // on為開啟;off為關閉
general_log_file = /var/log/generalLog.log // 審計資訊存儲位置
log_timestamps = SYSTEM // 設定日志檔案的輸出時間為地方時
修改my.cnf檔案和設定global變量的差別在于,設定global變量,則資料庫重新開機後設定就失效了。
而修改my.cnf檔案,資料庫每次啟動後,都會先去my.cnf讀取變量的值,再傳給相應的global變量。
下面其它變量也是如此。
另外要說的一點是,變量general_log的類型是bool,可以設定的值為OFF(或者0),以及ON(或者1),是以設定為ON和1是一個意思。
3.2. MariaDB的Audit Plugin插件
該插件可以用于MySQL的一些版本上,比如MySQL 5.7.18。
該插件的相關變量為:
SHOW GLOBAL VARIABLES LIKE 'server_audit%';
+-------------------------------+-----------------------+
| Variable_name | Value |
+-------------------------------+-----------------------+
| server_audit_events | CONNECT,QUERY,TABLE |
| server_audit_excl_users | |
| server_audit_file_path | server_audit.log |
| server_audit_file_rotate_now | OFF |
| server_audit_file_rotate_size | 1000000 |
| server_audit_file_rotations | 9 |
| server_audit_incl_users | |
| server_audit_logging | ON |
| server_audit_mode | 0 |
| server_audit_output_type | file |
| server_audit_query_log_limit | 1024 |
| server_audit_syslog_facility | LOG_USER |
| server_audit_syslog_ident | mysql-server_auditing |
| server_audit_syslog_info | |
| server_audit_syslog_priority | LOG_INFO |
+-------------------------------+-----------------------+
解釋如下:
server_audit_output_type:指定日志輸出類型,可為SYSLOG或FILE
server_audit_logging:啟動或關閉審計
server_audit_events:指定記錄事件的類型,可以用逗号分隔的多個值(connect,query,table),如果開啟了查詢緩存(query cache),查詢直接從查詢緩存傳回資料,将沒有table記錄
server_audit_file_path:如server_audit_output_type為FILE,使用該變量設定存儲日志的檔案,可以指定目錄,預設存放在資料目錄的server_audit.log檔案中
server_audit_file_rotate_size:限制日志檔案的大小
server_audit_file_rotations:指定日志檔案的數量,如果為0日志将從不輪轉
server_audit_file_rotate_now:強制日志檔案輪轉
server_audit_incl_users:指定哪些使用者的活動将記錄,connect将不受此變量影響,該變量比server_audit_excl_users優先級高
server_audit_syslog_facility:預設為LOG_USER,指定facility
server_audit_syslog_ident:設定ident,作為每個syslog記錄的一部分
server_audit_syslog_info:指定的info字元串将添加到syslog記錄
server_audit_syslog_priority:定義記錄日志的syslogd priority
server_audit_excl_users:該清單的使用者行為将不記錄,connect将不受該設定影響
server_audit_mode:辨別版本,用于開發測試
這裡我們比較關注的是server_audit_logging、server_audit_events、server_audit_output_type、server_audit_file_path、server_audit_file_rotate_size、server_audit_file_rotations、server_audit_file_rotate_now。
server_audit_logging:
即為是否開啟,bool類型,值為ON(1)以及OFF(0)。
server_audit_events:
記錄的事件,如果為空字元串,則代表記錄所有的事件。
CONNECT:連接配接、斷開連接配接和失敗的連接配接,包括錯誤代碼
QUERY:以純文字形式執行的查詢及其結果,包括由于文法或權限錯誤而失敗的查詢
TABLE:受查詢執行影響的表
QUERY_DDL:與QUERY相同,但隻篩選DDL類型的查詢(create、alter、drop、rename和truncate語句,create/drop[procedure/function/user]和rename user除外(它們不是DDL)
QUERY_DML:與QUERY相同,但隻篩選DML類型的查詢(do、call、load data/xml、delete、insert、select、update、handler和replace語句)
QUERY_DCL:與QUERY相同,但隻篩選DCL類型的查詢(create user、drop user、rename user、grant、revoke和set password語句)
QUERY_DML_NO_SELECT:與QUERY_DML相同,但不記錄SELECT查詢。(從1.4.4版開始)(do、call、load data/xml、delete、insert、update、handler和replace語句)
server_audit_file_path:
當server_audit_output_type為file時,将路徑和檔案名設定為日志檔案。如果指定的路徑作為目錄存在,那麼将在該目錄内建立名為“ server_audit.log”的日志。否則,該值将被視為檔案名。預設值“ server_audit.log”,這意味着将在資料庫目錄中建立此檔案。
server_audit_file_rotate_size、server_audit_file_rotations、server_audit_file_rotate_now:
當server_audit_output_type為file時,是否強制輪轉(server_audit_file_rotate_now),每個日志檔案的最大大小(server_audit_file_rotate_size),以及日志檔案的最大數量(server_audit_file_rotations)。
更多變量的相關的解釋可以檢視官方文檔:MariaDB Audit Plugin Options and System Variables
那麼,從這個插件的功能來看,基本上預設配置就可以滿足測評項的要求。
3.3. MySQL Enterprise Audit Plugin
MySQL 企業版的 Enterprise Edition 中自帶 Audit Plugin ,名為 audit_log.so。
對于該插件,可以在my.cnf檔案中加入以下參數啟用它:
[mysqld]
plugin-load=audit_log.so
也可以查詢插件,看到插件的狀态:
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE 'audit%';
+-------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+-------------+---------------+
| audit_log | ACTIVE |
+-------------+---------------+
該插件的相關系統變量為:
mysql> SHOW VARIABLES LIKE 'audit_log%';
+-----------------------------+--------------+
| Variable_name | Value |
+-----------------------------+--------------+
| audit_log_buffer_size | 1048576 |
| audit_log_connection_policy | ALL |
| audit_log_current_session | OFF |
| audit_log_exclude_accounts | |
| audit_log_file | audit.log |
| audit_log_filter_id | 0 |
| audit_log_flush | OFF |
| audit_log_format | NEW |
| audit_log_include_accounts | |
| audit_log_policy | ALL |
| audit_log_rotate_on_size | 0 |
| audit_log_statement_policy | ALL |
| audit_log_strategy | ASYNCHRONOUS |
+-----------------------------+--------------+
audit_log_connection_policy:
控制稽核日志插件如何将連接配接事件寫入其日志檔案的政策
audit_log_exclude_accounts:
不應記錄事件的帳戶,除此之外的賬戶的事件都會被記錄。該值應為NULL或包含一個或多個用逗号分隔的帳戶名清單的字元串。
audit_log_file:
日志記錄的檔案名,可以是相對路徑(相對于資料庫目錄)和完整路徑。
audit_log_format:
日志格式,可以是 OLD(舊樣式XML), NEW(新樣式XML,預設值)和(從MySQL 5.7.21開始)JSON。
audit_log_include_accounts:
要包括在稽核日志記錄中的帳戶。如果設定了此變量,則僅稽核這些帳戶。
注意,audit_log_exclude_accounts與audit_log_include_accounts是互斥的,它們之間隻有一個的值為非null,不能同時為非null。
audit_log_policy:
事件記錄政策
audit_log_rotate_on_size:
如果 audit_log_rotate_on_size 值為0,則稽核日志插件不會執行自動日志檔案輪換。而是手動使用audit_log_flush重新整理日志檔案。在這種情況下,請在重新整理檔案之前在伺服器外部手動重命名該檔案(要不然原來的記錄就沒了)。
如果該 audit_log_rotate_on_size 值大于0,則會自動進行基于大小的日志檔案輪換。每當寫入日志檔案導緻其大小超過該 audit_log_rotate_on_size 值時,稽核日志插件都會關閉目前日志檔案,将其重命名,然後打開一個新的日志檔案。
如果将此變量設定為不是4096的倍數的值,它将被截斷為最接近的倍數。(是以,将其設定為小于4096的效果是将其設定為0且不進行旋轉,除非手動進行。)
audit_log_statement_policy:
應該被記錄的語句事件,在伺服器啟動的時候如果audit_log_statement_policy和audit_log_policy都顯示賦予了值,那麼audit_log_statement_policy可能會被audit_log_policy覆寫。
更多詳細的解釋請看官方文檔:MySQL Enterprise Audit
基本上預設配置也足夠滿足測評項要求了。
3.4. McAfee的libaudit_plugin
也是一個稽核插件,其相關參數如下:
SHOW GLOBAL VARIABLES LIKE '%audi%';
audit_json_file #是否開啟audit功能(ON\OFF)
audit_json_log_file #log日志名稱及存儲位置,預設mysql的data目錄
audit_record_cmds='' #設定需要監控的SQL指令,預設全部(即該值為null)
audit_record_cmds='insert,delete,update,create,drop,alter,grant,truncate' #這是一些例子
audit_record_objs='' #設定需要監控的資料庫名稱和表名,預設全部(即該值為null)
audit_record_objs=‘mysql.*’ #一個例子
audit_whitelist_users #使用者白名單
更多詳細解釋請檢視官方文檔:McAfee的audit
基本上啟用後就滿足測評項要求了。
四、測評項b
b)審計記錄應包括事件的日期和時間、使用者、事件類型、事件是否成功及其他與審計相關的資訊;
隻要啟用了審計功能,無論是自帶的審計還是插件,在記錄的資訊上都能滿足這個要求。
4.1. 自帶的審計功能
其記錄内容如下:
mysql> select * from general_log;
| 2018-07-17 23:00:12 | root[root] @ localhost [] | 2 | 1132333306 | Query | select * from test.student3
4.2. MariaDB的Audit Plugin插件
其記錄内容如下:
日志的格式解釋可看官方文檔:MariaDB Audit Plugin – Log Format
4.3. MySQL Enterprise Audit Plugin
該插件的日志檔案可以是XML或者JSON格式,以XML為例:
<AUDIT_RECORD>
<TIMESTAMP>2019-10-03T14:09:38 UTC</TIMESTAMP>
<RECORD_ID>6_2019-10-03T14:06:33</RECORD_ID>
<NAME>Query</NAME>
<CONNECTION_ID>5</CONNECTION_ID>
<STATUS>0</STATUS>
<STATUS_CODE>0</STATUS_CODE>
<USER>root[root] @ localhost [127.0.0.1]</USER>
<OS_LOGIN/>
<HOST>localhost</HOST>
<IP>127.0.0.1</IP>
<COMMAND_CLASS>drop_table</COMMAND_CLASS>
<SQLTEXT>DROP TABLE IF EXISTS t</SQLTEXT>
</AUDIT_RECORD>
相似的格式介紹請檢視官方文檔:稽核日志檔案格式
4.4. McAfee的libaudit_plugin
該插件日志檔案的格式是json:
{
"msg-type": "activity",
"date": "1510038432019",
"thread-id": "43",
"query-id": "1891",
"user": "root",
"priv_user": "root",
"ip": "",
"host": "localhost",
"connect_attrs": {
"_os": "linux-glibc2.5",
"_client_name": "libmysql",
"_pid": "4009",
"_client_version": "5.7.9",
"_platform": "x86_64",
"program_name": "mysql"
},
"pid": "4009",
"os_user": "root",
"appname": "mysql",
"rows": "1",
"cmd": "insert",
"objects": [
{
"db": "part",
"name": "e",
"obj_type": "TABLE"
}
],
"query": "insert into e values (9898,'smart','james')"
}
詳細的格式介紹請檢視官方文檔:mysql-audit
五、測評項c
c)應對審計記錄進行保護,定期備份,避免受到未預期的删除、修改或覆寫等;
5.1. 要求1
對審計記錄進行保護,那麼這裡就不細說了,說一下大概的原則。
無論是自帶的審計還是審計插件,如果稽核記錄存儲于檔案中的,應該在作業系統上對這些日志檔案的權限進行限定,僅允許資料庫管理者可對這些檔案進行通路、修改等。同時也要限制MySQL中的file_priv權限。
如果稽核記錄存儲于資料庫表中,那麼也應該對資料庫的表進行權限設定,僅資料庫管理者可對稽核記錄表進行通路、修改等。
5.2. 要求2
定期備份就不用多做什麼說明了,檢查備份檔案和備份政策即可。
在這裡有一個地方想探讨下,在等級保護2.0試行稿中,對日志的留存時間有要求:
這裡的法律法規要求一般來說指的就是《網絡安全法》,其中有關日志留存時間的條款如下:
(三)采取監測、記錄網絡運作狀态、網絡安全事件的技術措施,并按照規定留存相關的網絡日志不少于六個月;
在等保正式2.0正式稿中,這個測評項被删除了,那麼《網絡安全法》對于日志留存時間(6個月)的要求是否落在了測評項c當中呢?
從基本要求來看,應該不是,其中沒有這個要求:
當然,既然網絡安全法這麼規定了,等級保護肯定還是有測評項來實作該要求的,就是在安全管理中心的集中管控的測評項中:
按照我的個人了解,6個月的留存時間要求,應該是在集中管控的c測評項中去落實。
怎麼測評呢?首先肯定要有相關的審計裝置,也就是資料庫審計以及綜合日志審計裝置,沒有這些裝置,集中管控d測評項的第一個要求就沒法滿足。
然後在這些裝置中,檢視彙總的審計記錄留存時間是否滿足了法律法規的要求。
也就是,不需要跑去單個的裝置上,檢視每個裝置的審計記錄是否滿足法律法規的要求。
否則,等級保護2.0正式稿中就不會将應確定審計記錄的留存時間符合法律法規要求挪到集中管控裡面去了。
為什麼說到這個呢?因為我在初級教程裡看到了關于留存時間的要求:
綜上所述,我個人覺得關于日志留存時間6個月的要求,應該再集中管控的d測評項中進行統一描述,而不是在每個測評對象的安全審計的c測評項中進行描述。
六、測評項d
d)應對審計程序進行保護,防止未經授權的中斷。
這個就比較簡單了,有兩個地方可以對審計程序進行配置。
一個是my.cnf,這裡就需要作業系統上對配置檔案的權限進行限制,隻允許資料庫管理有權限進行修改。(同時也要限制MySQL中的file_priv權限。)
另外一個就是那些變量了,似乎是需要super權限才可以設定全局變量,那麼這裡的話就需要檢視super權限給了哪些賬戶。