phpMyAdmin 的 display_errors 必须在 php.ini、Apache 或 Nginx 配置中全局关闭,不能靠 config.inc.php 临时设置;log_errors 应开启,且 error_log 必须设为 Web 不可访问路径(如 /var/log/phpmyadmin/error.log)。
phpMyAdmin 的 display_errors 必须关,不能靠代码临时关
phpmyadmin 本身是 php 应用,但它的错误输出完全受 php 全局配置控制。你在 config.inc.php 里写 ini_set('display_errors', '0') 或 error_reporting(0) 是无效的——因为 phpmyadmin 的入口文件(index.php)在加载配置前就可能触发错误(比如扩展缺失、session_start() 失败),此时自定义设置根本没机会执行。
真正起作用的只有 php.ini 级别或 Web 服务器运行时指令:
- Apache 下必须在虚拟主机或
.htaccess中加:php_flag display_errors off - Nginx 下必须在
server块中加:fastcgi_param PHP_VALUE "display_errors=Off"; - 直接改 php.ini 更稳妥,但需确认该配置被 phpMyAdmin 实际加载(查
phpinfo()中 “Loaded Configuration File” 和 “Local Value” 对应的display_errors)
log_errors 要开,但日志路径不能放在 web 可访问目录下
关闭显示不等于不记录。如果 log_errors = On 但 error_log = /var/www/html/phpmyadmin/error.log,攻击者只要知道路径就能下载日志——里面可能含完整堆栈、$_SERVER['SCRIPT_FILENAME']、甚至数据库连接失败时的 DSN 片段。
安全做法是把日志写到 Web 根目录之外:
- Linux 示例:
error_log = /var/log/phpmyadmin/error.log - 确保 PHP 进程用户(如
www-data)对该路径有写权限:sudo chown www-data:www-data /var/log/phpmyadmin/ - 检查日志是否真被写入:
tail -f /var/log/phpmyadmin/error.log,再手动触发一个语法错误(如在config.inc.php末尾加<?php xyz;)
config.inc.php 里别留调试痕迹,尤其不能 echo 或 print_r
很多人为了“验证配置是否生效”,在 config.inc.php 开头加 echo 'loaded'; die(); 或 print_r($_SERVER);,这会导致整个文件被当作纯文本输出——不仅泄露路径,还可能暴露 HTTP_HOST、REMOTE_ADDR、甚至 PHP_SELF 拼接出的绝对路径。
立即学习“PHP免费学习笔记(深入)”;
这类调试代码上线前必须删干净。更隐蔽的风险是注释里的敏感信息:
- ❌ 错误示例:
// dev DB: host=127.0.0.1 user=root pass=123456 - ✅ 正确做法:所有密码、host、端口等只出现在
$cfg['Servers'][$i]['host']等赋值语句中,且配置文件本身移出 Web 根目录(见下一条)
phpMyAdmin 目录必须置于 Web 根目录外,或用服务器规则彻底封死
即使你关了 display_errors,只要 phpmyadmin/ 目录在 Web 可访问路径下(如 /var/www/html/phpmyadmin/),一旦 PHP 解析失败(模块崩溃、.php 后缀未注册),浏览器直接 GET 就会返回明文源码——config.inc.php 里的数据库账号密码全裸奔。
最可靠的是物理隔离:
- 把 phpMyAdmin 解压到
/usr/share/phpmyadmin/(系统级路径,非 Web 根目录) - 在 Nginx/Apache 中用别名(
alias)或符号链接指向它,同时确保location ~ \.php$规则仍能正确转发 - 若必须放 Web 目录内,则 Apache 需加全局拒绝规则:
<Files "config.inc.php"> Require all denied </Files>;Nginx 则加:location ~ ^/phpmyadmin/config\.inc\.php$ { return 404; }
路径隔离和服务器规则缺一不可,单靠其中一种容易被绕过。



















