MySQL从库必须设read_only=ON且super_read_only=ON才能真正防误写,否则phpMyAdmin等客户端仍可执行写操作;需在/etc/my.cnf[mysqld]段按序配置并重启,同时严格限制账号权限。
MySQL从库必须设read_only = ON,否则phpMyAdmin无法阻止写入
phpmyadmin本身不控制数据库读写权限,它只是把sql原样发给mysql。如果从库没开read_only,用户在sql标签页里执行update、delete或drop table照样成功——界面没按钮、菜单被隐藏都没用。
关键操作只有两步:SET GLOBAL read_only = ON,再SET GLOBAL super_read_only = ON(顺序不能反,否则报ERROR 1290)。但仅SET GLOBAL重启即失效,永久生效必须写进/etc/my.cnf的[mysqld]段,并确保super_read_only = ON写在read_only = ON之后,否则MySQL启动失败。
- 验证是否生效:登录从库执行
SELECT @@read_only, @@super_read_only,两个值都应为1 - 常见误判:看到
read_only = 1就以为安全了,但super_read_only = 0时,有SUPER权限的账号仍可绕过 - 注意权限冲突:如果phpMyAdmin用的账号有
SUPER权限,它能直接关掉read_only,所以该账号必须撤掉SUPER
phpMyAdmin账号必须无INSERT/UPDATE/DELETE权限
即使MySQL层开了read_only,只要账号本身有写权限,phpMyAdmin仍会显示“编辑”“插入”“删除”按钮,用户点一下就触发SQL——而MySQL此时会因read_only报错,但界面不会提前拦截。
真正防误写,得让账号在MySQL里只拥有SELECT和SHOW VIEW等只读权限。操作路径是:phpMyAdmin → “用户账户” → 找到该账号 → “编辑权限” → 全局权限全取消 → 在“数据库特权”里只为必要库勾选SELECT。
- 别信“只给某个库权限就安全了”:如果账号对
mysql库有INSERT,它就能往pma__bookmark表写恶意SQL,别人点书签就中招 - 检查
GRANT OPTION:这个权限能让用户给自己加权限,必须禁用 - 旧版MySQL(account_locked,临时禁用账号时别清空密码,改
plugin为auth_socket更可靠
phpMyAdmin配置要关掉可能诱导写操作的功能
有些功能看似只读,实则暗藏写入口。比如“复制表”“创建视图”“生成SQL”等操作,背后都会发出CREATE或ALTER语句。这些不是靠MySQL权限拦得住的,得在phpMyAdmin层面关掉。
立即学习“PHP免费学习笔记(深入)”;
在config.inc.php里加这几行:
$cfg['Servers'][$i]['DisableIS'] = true; // 关闭Information Schema访问,防止探测库结构 $cfg['ShowSQL'] = false; // 隐藏SQL执行框,减少手误风险 $cfg['EnableAutocomplete'] = false; // 关闭自动补全,避免提示出INSERT/UPDATE关键字
-
$cfg['Servers'][$i]['DisableIS'] = true比单纯隐藏菜单更硬:它让phpMyAdmin连SHOW TABLES都拿不到完整列表,自然没法生成建表语句 - 不要只关“导入”功能(
$cfg['UploadDir'] = ''):导出功能若开着,用户可能导出CSV再手动改后缀上传成PHP WebShell - 所有改动必须重载浏览器,phpMyAdmin不自动刷新配置
最后一步:验证INTO OUTFILE和LOAD DATA是否真被堵死
攻击者最常绕过只读限制的方式就是SELECT ... INTO OUTFILE写WebShell,或LOAD DATA INFILE读取服务器敏感文件。这两条路必须从MySQL底层掐断,不能只靠phpMyAdmin界面。
先执行REVOKE FILE ON *.* FROM 'pma_user'@'%',再在my.cnf里设secure_file_priv = /tmp/(绝不能为空字符串),重启MySQL。然后手动测试:
SELECT 'test' INTO OUTFILE '/tmp/test.txt'; -- 应报ERROR 1290或1045 LOAD DATA INFILE '/etc/passwd' INTO TABLE t1; -- 应报ERROR 1290
- 如果
INTO OUTFILE还能成功,说明FILE权限没撤干净,或者secure_file_priv没生效 - phpMyAdmin的“导出”按钮即使灰掉,用户仍可能在SQL标签页里手敲
INTO OUTFILE,所以权限+参数双保险缺一不可 - 别忽略磁盘空间:
read_only在磁盘满时会自动失效,定期监控/var/lib/mysql剩余空间



















