1. 程式人生 > >給自己一個更安全的 mysql

給自己一個更安全的 mysql

0x01 在進行真正的 mysql 部署之前,我們不妨先來大致瞭解下,在實際入侵過程中,僅僅利用mysql,我們到底能幹些什麼,瞭解了這些最基本的點之後,我們再進行鍼對性防禦:

 

1

2

3

4

 

普通使用者許可權下的 '增刪改查',即 常規sql注入,俗稱'脫褲'

普通使用者file許可權下的 '檔案讀寫',可嘗試讀取各類敏感配置,如各類賬號或者嘗試直接往站點目錄中寫webshell

root使用者許可權下的 '讀寫檔案' , '系統命令執行'... 可讀寫是因為root本身就有file許可權,另外,如果直接以root身份執行mysql服務,亦可實現'提權'的效果

針對 '資料庫連線' 的'DDOS',單使用者大批量資料庫連線可能會導致mysql無法再提供服務

 

0x02 演示環境:

 

1

2

 

CentOS6.8 x86_64 最小化,只帶基礎庫安裝 eth0: 192.168.3.42 eth1: 192.168.4.14 eth2: 192.168.5.14

mysql-5.6.27-linux-glibc2.5-x86_64.tar.gz 此次mysql就不再手工編譯了,時間比較長,直接用mysql官方提供好的二進位制包來做演示

 

0x03 下載,解壓 mysql-5.6.27-linux-glibc2.5-x86_64.tar.gz

 

1

2

3

4

 

# tar xf mysql-5.6.27-linux-glibc2.5-x86_64.tar.gz

# mv mysql-5.6.27-linux-glibc2.5-x86_64 /usr/local/

# ln -s /usr/local/mysql-5.6.27-linux-glibc2.5-x86_64/ /usr/local/mysql

# ls -l /usr/local/mysql/

 

0x04 開始初始化mysql

務必以一個偽使用者身份來執行mysql服務,防止別人利用mysql進行提權,後面還會再細說,另外,web服務和資料庫服務嚴禁用同一個系統使用者,這樣做主要是為了防止入侵者直接通過sql語句往網站目錄中寫webshell

 

1

 

# useradd -s /sbin/nologin -M mysql

 

 

1

2

3

4

5

6

 

# chown -R mysql.mysql /usr/local/mysql/ && ll /usr/local/mysql/ 暫時先讓mysql使用者對mysql的安裝目錄能正常讀寫

# /usr/local/mysql/scripts/mysql_install_db --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/ --user=mysql

# chown -R root.root /usr/local/mysql/ && ll /usr/local/mysql/

# chown -R mysql.mysql /usr/local/mysql/data/ && ll /usr/local/mysql/data/

# cp /usr/local/mysql/support-files/my-default.cnf /etc/my.cnf 建立mysql配置檔案

# /usr/local/mysql/bin/mysqld_safe & 啟動mysql服務

把mysql工具包加到root使用者的環境變數中,方便後續使用,切記不要放到全域性環境變數下,那意思就是說當前系統所有普通使用者也都可以使用mysql工具套件

 

1

2

3

4

 

# echo "export PATH=$PATH:/usr/local/mysql/bin/" >> .bash_profile

# source .bash_profile

# mysql

# killall mysqld

 

0x05 讓 mysql 隨系統自啟動的兩種方式,更推薦前者,實際中大家可根據個人習慣而定:

第一種:

 

1

 

# echo "/usr/local/mysql/bin/mysqld_safe &" >> /etc/rc.local

 

第二種:

 

1

2

3

4

5

6

 

# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld

# chmod +x /etc/init.d/mysqld

# ll /etc/init.d/mysqld

# /etc/init.d/mysqld start

# lsof -i :3306

# /etc/init.d/mysqld stop

 

0x06 mysql初始化後的基礎配置:

設定複雜root密碼,關於密碼安全在之前已無數次強調,此處就不細說了吧,同時包含大小寫,特殊字元,12位以上的隨機密碼,越隨機越好,這裡純粹只是為了演示

 

1

2

 

# /etc/init.d/mysqld start

# mysqladmin -uroot password "admin"

 

設定好root密碼後,立刻進到mysql下,刪除多餘資料庫,如,test庫…,如下

 

1

2

3

 

# mysql -uroot -p

mysql> show databases;

mysql> drop database test;

 

清除多餘資料庫使用者,只保留rootlocalhost127.0.0.1即可,如下

 

1

2

3

4

5

6

7

8

9

10

11

 

mysql> select user,host from mysql.user;

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

| user | host |

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

| root | 127.0.0.1 |

| root | ::1 |

| | localhost |

| root | localhost |

| | oldlnmp |

| root | oldlnmp |

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

 

 

1

2

3

4

5

6

7

8

9

10

11

12

 

mysql> drop user ''@'localhost';

mysql> drop user ''@'oldlnmp';

mysql> drop user 'root'@'oldlnmp';

mysql> drop user 'root'@'::1';

mysql> select user,host from mysql.user;

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

| user | host |

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

| root | 127.0.0.1 |

| root | localhost |

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

0x07 從根源上限制住 mysql 在系統中的各種許可權 [ 暫以防止伺服器被入侵為最終目的,此處是防不住別人正常的增刪改查的,如,'脫褲' ]

首先,儘可能讓mysql服務執行在一個較低的系統許可權下,防止別人利用該服務提權,如,常見的udf提權,這裡有些朋友可能會誤解,以為只能要能執行系統命令,就是提權,其實不然,在linux中,普通使用者也一樣可以執行大部分系統命令,但,它依然只是個普通使用者,提權的意思就是讓你從一個普通使用者甚至是一個偽使用者身份的許可權下直接提升到了root許可權,言歸正傳,因為我們當前執行mysql服務的使用者只是一個系統偽使用者,也就是說,你當前執行任何sql語句所對映的許可權,都是你mysql服務使用者的許可權,如果這個服務使用者許可權本身就很低,也一樣達不到提權的效果,相對來講,udf提權更適合用在一些比較古老的系統<= win2003和較低的一些mysql版本上<= mysql 5.1,新版的mysql除了效能優化之外,安全性也有大幅提升,話說回來,即使安全性提升了,也還是保不住傻逼的配置,之前在win平臺下,也許還可以想辦法通過dll劫持的方式來進行提權,但5.6.x已經很好的修復了這些問題,對程序的安全上下文也做了更為嚴格的控制

 

1

 

# useradd -s /sbin/nologin -M mysql

 

嚴格控制住mysql安裝目錄在本地檔案系統中的許可權,我們再來簡單回顧一下上面初始化mysql的詳細過程,如下,在初始化之前,首先,我們建立了一個系統偽使用者mysql,接著我們把mysql安裝目錄的屬主,屬組都改成了mysql,意思就是先讓mysql使用者對mysql的安裝目錄暫時能寫,因為等會兒要初始化mysql,會生成一些mysql內部系統配置,比如,mysql系統庫,所以,必須要讓mysql使用者對mysql的安裝目錄能寫才行,緊接著,我們指定了mysql的安裝目錄和資料存放目錄,以及執行mysql服務時的系統使用者 [ 即mysql使用者 ],嘗試進行初始化操作,這裡務必注意,在第一次初始化完成後,我們後續的許可權就不需要那麼大了,所以,又把mysql安裝目錄的屬主,屬組都改成了root,因為最終還要保證別人能正常的往資料庫中寫資料,所以,data目錄的屬主要再改回mysql,說到這份上,想必大家此時都已經非常清晰了吧

 

1

2

3

4

 

# chown -R mysql.mysql /usr/local/mysql/ && ll /usr/local/mysql/

# /usr/local/mysql/scripts/mysql_install_db --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/ --user=mysql

# chown -R root.root /usr/local/mysql/ && ll /usr/local/mysql/

# chown -R mysql /usr/local/mysql/data/ && ll /usr/local/mysql/data/

 

0x08 關於 mysql自身的一些安全配置

在通過上面的一些初步加固後,別人此時再想單單通過mysql拿到伺服器許可權就比較困難了,畢竟,是從根源上進行控制的,下面我們就再來對針對mysql自身配置做些簡要優化

為每個站點,建立獨立的資料庫以及資料庫使用者,只允許該使用者對該庫有最基本的增刪改查許可權且只能讓特定的內網ip才能訪問到,有條件,最好站庫進行分離,分離的好處在於可以讓入侵者無法再正常讀寫檔案,畢竟不在同一臺機器上,因為資料庫伺服器上,根本沒有web服務,即使僥倖找到了物理路徑,也沒啥大用,此外,要嚴格遵守密碼複雜性要求,其實,實際生產環境中,這些許可權已經基本能夠適應所有日常業務需求,別的許可權一律不要加,另外,在授權時,也可通過shell指令碼自動對指定庫中除管理或系統表之外的其它表進行一一單獨授權,而管理表則單獨授權給其它資料庫使用者,這樣做的好處就是,此時即使存在sql注入,也讓入侵者沒法通過跨表來查網站後臺管理的賬號和密碼hash,有些許可權對普通使用者來講是完全沒必要的,如,file,如果讓普通使用者都有file許可權,也就意味著入侵者可以通過mysql往你伺服器本地檔案系統中讀寫檔案,雖然,我們是可以對本地檔案系統進行詳細許可權控制,但還是會造成一部分資訊洩露,畢竟有些許可權,我們是不太好動的,比如,/tmp下,所以,這些危險許可權統統的不要,當然,一些非常重要的業務資料表,也可以單獨授權給另一個使用者進行相互隔離,如果業務邏輯比較複雜,這樣做確實麻煩,可以嘗試慢慢把業務整理拆分出來,雖然,我們可以利用mysql輕鬆把許可權控制到表級別,但實際中還是非常建議’一站一庫’,這樣後續維護管理起來也非常方便規整

 

1

2

3

4

5

6

7

8

 

mysql> create database sec_list;

mysql> create user 'klion'@'192.168.3.70' identified by 'admin';

mysql> create user 'sec'@'192.168.3.70' identified by 'admin';

mysql> grant insert,delete,update,select,create,drop on sec_list.* to [email protected]'192.168.3.70' identified by 'admin';

mysql> grant insert,delete,update,select,create,drop on sec_list.admin to [email protected]'192.168.3.70' identified by 'admin';

mysql> flush privileges;

mysql> show grants for 'klion'@'192.168.3.70'; 查詢指定資料庫使用者的系統許可權

mysql> revoke select on sec_list.* from 'sec'@'192.168.3.70'; 撤銷指定使用者的指定許可權

 

嚴禁允許root使用者外連,正常來講,不僅僅是root不允許外連,有條件的情況下,mysql服務埠都不要對外開放,只允許特定的內網ip段來連線,另外,所有的實際業務嚴禁直接用mysql的root使用者身份來處理,強烈建議,不同的業務需求,直接建立對應的資料庫普通賬戶來處理即可

 

1

 

mysql> grant all on *.* to 'root'@'%' identified by 'admin' with grant option;flush privileges; 嚴禁用語句對root重新授權

 

把root使用者改個比較另類的名字,越看不出來是幹啥的越好,嘿嘿……說實話個人覺得沒啥用,如果真的存在sql注入,隨便用sql語句查下許可權就知道了,另外,sqlmap裡的–is-dba也不是白給的,不過這樣做的好處,倒是可以一定程度上防爆破

 

1

2

3

 

mysql> use mysql;

mysql> update user set user='root' where user='guest';

mysql> flush privileges;

 

至於修改埠,其實,也沒啥大用,通過各種服務指紋識別及埠掃描工具依然可以快速探測出來,即使一下掃65535個埠,現在對nmap來講也並不是太慢,修改埠的方法比較簡單,只需要改下mysql配置檔案mysqld模組下port欄位即可

 

1

 

# vi /etc/my.cnf

 

0x09 定時遠端同步 mysql 服務的各類日誌,方便後續審查日誌快速匹配出裡面的各種sql注入攻擊特徵,如,information便是非常好的關鍵字,觀察哪些是執行成功的,儘可能回溯到可能存在sql注入的指令碼程式碼段,並主動修復該漏洞,生產環境中的mysql可能瞬間併發都很高,如果此時再啟用查詢日誌,資料庫的壓力可想而知,所以,適時取捨

 

1

2

 

# tail -f /usr/local/mysql/data/OldLnmp.err

mysql> show variables like 'log_%'; 檢視各類日誌存放位置和開啟情況

 

0x10 利用各種實時日誌分析平臺,實時快速捕捉各種常見資料庫攻擊特徵,如,ELK,Splunk…目前還在研究學習中,離實戰應用還有些距離,欠著,待續…

0x11 注意對重要業務資料定時備份,這些不用說,想必大家也很清楚,相信絕大部分都早已主從同步了

0x12 限制單使用者連線數,防止拒絕服務

0x13 這可能也是我們對mysql的最後一道補救防線,刪除各種歷史檔案,如下,其實說白點,既然能到這一步,說明別人此時已經拿到shell了,這樣做也純粹是自我安慰罷了,只能說讓入侵者儘量蒐集不到什麼有價值的資訊

 

1

2

3

4

 

# history -w 先把當前所有的歷史記錄寫到命令歷史檔案中去

# vi .bash_history 然後編輯該檔案,把裡面所有的關於mysql的操作全部刪除

# history -w && history 最後,再更新檔案,看看剛剛刪掉的那些記錄還在不在

# rm -fr .mysql_history 刪掉mysql操作歷史

 

0x16 最後,定期去關注mysql官方釋出的高危補丁,適時進行修補

0x17 關於sql注入各種利用,屬於指令碼漏洞範疇,並不在今天的討論範圍內,對此,後續還會有大量詳細的說明,此處不再贅述

0x10 利用各類入侵檢測系統,自動檢測識別惡意脫褲流量,暫時還沒啥特別好的思路,也非常期待能和大家一起多交流

0x18 更多,待續…



小結:
    還是那句話,此處所說的一切加固,全部是建立在確認自己目前還沒被別人成功入侵或者別人手裡沒有可用遠端0day的情況下,如果是這樣,剛才說的這些,就差不多已經能把mysql整個許可權牢牢的控死在搖籃裡,另外,還有一些邊緣性的無關痛癢的安全配置,單從入侵的角度來講,那些並不重要,所以就沒仔細說,個人性格比較鮮明,從寫文章的風格大家也隱約能感覺到,哼哼…一刀斃敵慣了,不太喜歡廢話,話不在多,點中即可,畢竟,我們不是在做學術研究,而是貼近實戰,真刀真槍的幹,另外,不要問我為什麼不把mysql部署在windows上,是的,我承認自己對windows掌握的並不好 [ 除了域,如果你認為只是點點圖形介面上的按鈕就叫會了,那我無話可說,如果都這麼簡單,那就不叫作業系統了,叫玩具也許會更合適些 ],可能跟大家不太一樣的是,因為各種陰差陽錯的原因,自己真正的啟蒙作業系統是linux[ 哈哈,沒接受過大學正規教育的悲哀 ],不過,這也讓我對整個作業系統有了自己的理解和認識,相信用linux的思維方式來思考問題,你會看到另一個世界,簡潔,高效,可控而美麗,哼哼,反正,對於linux真心覺得越用越覺得好用,等你用到一定程度,你就會感覺到,它對你幾乎是完全透明的,有著非常強的把控感,而windows給自己的感覺則是無盡的恐怖與未知,大家可能也看出來了,和傳統的安全運維不太一樣,我們更加專注於防入侵,說心裡話,如果你對系統的許可權分配機制專業叫法 [ 安全上下文 ]已經理解的非常透徹了,毫不誇張的說,這些東西對你來講,簡直易如反掌,真的,當然,這裡所說的簡單,並非指那些所謂的命令工具,而是你可以根據自己實際的業務需求,進行更加合理靈活的許可權控制,另外,豐富的實戰滲透經驗也是必不可少的,說一千道一萬,很多問題,如果當初就嚴格按照安全規範來操作是很難出什麼問題的,一切還以實際業務需求和效能為主,不多說了,祝大家好運吧 ^_^