必须设置$cfg['ShowStats'] = false关闭数据库统计,否则即使前端隐藏,AJAX接口仍返回各库表数、大小等敏感信息;同时需配合REVOKE SELECT ON information_schema.*和$cfg'Servers'['hide_db']正则屏蔽系统库。
数据库统计信息本身就是攻击者的侦察地图
phpmyadmin 默认在首页或数据库列表页展示「数据库统计」栏(如 information_schema 有 64 张表、mysql 占用 2.1 mib),这些数字不是装饰——它们直接暴露了目标环境的结构细节。攻击者不需要登录,只要能访问 phpmyadmin 登录页(甚至未登录状态下的错误提示、http 响应头、页面源码注释),就可能拿到这些统计值。一旦知道某库表数异常多、某库体积突增,就能反向推测:是否刚上线新业务?是否存有日志/备份/临时数据?是否用了特定框架(如 laravel 的 migrations 表)?这比盲扫快得多。
$cfg['ShowStats'] = false 是唯一有效的关闭方式
这个配置项控制服务端是否生成并返回统计字段,不是前端 CSS 隐藏。不设它,即使你用 JS 把「#serverinfo」区域 display: none,浏览器 Network 面板里仍能看到 ajax.php?server=1&ajax_request=1&get_server_stats=1 返回完整 JSON,含各库精确表数、大小、字符集等。
-
$cfg['ShowStats'] = false;必须写在config.inc.php中,放在$cfg['Servers'][$i]配置块之后、任何require之前 - 别和
$cfg['ShowServerInfo']混淆——后者只关顶部服务器版本行,不影响数据库级统计 - 改完必须重启 Web 服务(如
sudo systemctl restart apache2)或清空 OPcache,否则 PHP 缓存会继续吐旧数据
隐藏统计 ≠ 阻断元数据查询,权限层必须同步收紧
关闭统计只是去掉聚合摘要,但攻击者仍可通过 SQL 手动查:SELECT table_schema, COUNT(*) FROM information_schema.TABLES GROUP BY table_schema。所以:
- MySQL 层必须回收普通账号对
information_schema的SELECT权限:REVOKE SELECT ON information_schema.* FROM 'user'@'host'; - phpMyAdmin 的
$cfg['Servers'][$i]['hide_db']正则(如'/^(information_schema|sys)$/i')要配合使用,避免该库出现在左侧导航——否则用户点开空库时,界面报错反而泄露存在性 - 注意 MySQL 8.0+ 对
information_schema.STATISTICS默认禁读,但TABLES和SCHEMATA仍开放,不能误以为“升级就安全”
真正容易被忽略的泄露点:导出功能与错误响应
很多人关了首页统计,却忘了导出页和错误场景:
- 导出时若选「结构 + 数据」,生成的 SQL 文件头部常带注释:
-- Host: localhost Database: myapp,而myapp这个库名本身就在暴露业务范围 - 执行非法 SQL(如
SELECT * FROM nonexist)时,MySQL 错误信息默认包含完整数据库名和表名,需在 MySQL 配置中设sql_mode = STRICT_TRANS_TABLES并关闭show_errors(通过 phpMyAdmin 的$cfg['ShowSQL'] = false只影响界面,不改 MySQL 行为) - PHP 错误报告若开启(
display_errors = On),连接失败时可能直接打印mysqli_connect(): (HY000/1045): Access denied for user 'xxx'@'%' using password: YES——连用户名格式都给了
关掉统计只是去掉一张明牌,但整副牌还在桌上。真正防范侦察,得让攻击者既看不到汇总数字,也拿不到单条元数据,更无法从错误和导出物里拼出轮廓——三层动作缺一不可。
立即学习“PHP免费学习笔记(深入)”;



















