1.UDF是什么?
UDF (user defined function),即用户自定义函数。是通过添加新函数,对MySQL的功能进行扩充,其实就像使用本地MySQL函数如 user() 或 concat() 等。文件后缀为‘.dll’,常用c语言编写。
可通过sqlmap或者msf获取udf文件。
2.场景
不能外连但是可通过webshell连接数据库或者可以外连数据库时,并且通过一些手段(如配置文件)获得了数据库的高权限账户密码,就可以使用UDF提权。
3.条件
1.获得账户密码。并且有root/system权限(UDF提权的权限取决于mysql数据库账户的权限。)
3.知道绝对路径。
2.有导入/导出权限—security-file-priv为空值。 在mysql5.5之前 secure_file_priv默认是空,之后 secure_file_priv默认是NULL即不允许导入/导出。可在my.ini配置文件中修改,但是需要重启,实战不建议用。
4.UDF导入路径
- mysql<5.0,任意路径皆可
- 5.0 <= Mysql < 5.1Win2000导出路径: C:/Winnt/udf.dll; 其他Windows系统导出路径均为:C:/Windows/udf.dll或C:/Windows/system32/udf.dll
- 在mysql>=5.1的版本中,将 udf 文件导入到mysql安装目录‘lib/plugin’目录下,如果mysql安装时不选择完整安装或使用集成开发环境等情况下lib\plugin目录大概率是不存在的,可使用webshell创建lib\plugin目录。没有webshell或webshell无权限创建目录时可以使用ADS文件流创建目录(成功概率低)
- 可通过select version()查看mysql版本,若>=5.1可通过show variables like ‘%plugin%’;命令确定plugin路径。
5.导入UDF文件方法
有webshell直接上传至对应目录即可
没有webshell时需要以16进制编码写入udf文件。
16进制:select 0x4d5a900..... into dump file "xxx\\lib\\plugin\\udf.dll";
首先将对应版本的udf文件进行16进制编码
将16进制编码后udf文件使用dumpfile函数写入磁盘(outfile导出文件会在末尾写入新行且转义换行符,破坏二进制文件结构,dumpfile不会进行任何操作)。
注意:如果在低版本系统环境下(win2003)或部分特殊环境使用mysql命令提示符进行提权操作,由于不同环境下的mysql命令提示符可输入字符最大长度不同(win2003为8191,win10系统为65535),无法使用dumpfile一次性写入全部16进制字符,则需要将udf文件的16进制编码字符先进行切割,再拼接写入到一个表中,最后导出到目标系统。
在进行16进制数据切割时,每段字符的长度要为4的倍数,2进制转为16进制使用取四合一法,如果位数不够会在最高位补0,补0后会破坏原始二进制文件的文件结构导致利用失败,这也是很多人此方法复现失败的原因。需要mysql用户具有insert,update权限。
select 表 from udf into dumpfile "xxx\\lib\\plugin\\udf.dll";
6.利用
将udf导入到对应目录下后还不能执行命令,因为还需要引入才可以使用udf中定义的函数如sys_eval,sys_exec。类似于面向对象编程时引入包一样,如果没有引入包,那么这个包里的类你是用不了的。
sys_eval,执行任意系统命令,并将输出返回,所以一般使用此函数。
sys_exec,执行任意系统命令,并将退出码返回(无命令执行结果回显)。
引入命令
create function sys_eval returns string soname 'udf.dll';
两个变量:
一个是 function_name(函数名),我们想引入的函数是 sys_eval。
还有一个变量是 shared_library_name(共享包名称),即 udf.dll 。
然后就能执行命令了
select sys_eval('whoami');