4.9.x仍需手动加固,因CSRF防护不全、unserialize()未启用allowed_classes、setup.php未禁用、LFI校验残留等问题未彻底修复;必须删除或拦截setup.php、清理urldecode调用、强化checkPageValidity()、统一加固unserialize()。
phpmyadmin 4.9.x 版本(尤其是 4.9.0–4.9.7)虽已修复部分高危漏洞(如 cve-2018-12613 lfi),但仍存在未完全修复或新暴露的风险点,不能视为“安全终点”。直接升级到 5.2.2+ 才是根本解法;若因兼容性必须卡在 4.9.x,则需针对性补漏,而非依赖版本自带防护。
为什么 4.9.x 仍需手动加固?
官方在 4.9.0 中重写了 checkPageValidity() 并移除了双重 urldecode(),堵住了 CVE-2018-12613 的核心路径,但以下问题依然存在:
- CSRF 防护不覆盖全部敏感操作(如服务器管理页
server_databases.php在 4.9.x 中无 token 校验) -
unserialize()调用点未统一启用['allowed_classes' => false](PHP 7.0+ 才支持,但 4.9.x 代码中多数仍裸调用) -
setup.php虽被标记废弃,但在 4.9.7 中仍默认存在且未加拦截逻辑 - 部分文件(如
gis_data_editor.php)的路径校验逻辑未彻底重构,仍可能被绕过
必须立即禁用 setup.php 入口
setup.php 是 4.9.x 中唯一仍保留反序列化入口的脚本,攻击者可通过 POST configuration 触发 unserialize() —— 这个功能本就不该存在于生产环境。
- 最稳妥做法:直接删除
/scripts/setup.php文件(官方 4.9.0+ 已声明废弃) - 若需保留调试用途,在文件开头插入强制退出:
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['configuration'])) { http_response_code(403); die('Disabled.'); } - Nginx 层兜底拦截:
location ~ ^/scripts/setup\.php$ { return 403; } - Apache 层等效规则:
RewriteRule ^/scripts/setup\.php$ - [F]
修补 index.php 和 core.php 中的 LFI 校验残留
即使升级到 4.9.7,index.php 第 465 行附近仍可能残留未清理的 urldecode($page) 调用(尤其在自定义修改过的部署中),且 core.php 中的 checkPageValidity() 函数若未同步更新,白名单校验会被绕过。
- 定位
index.php中形如$page = urldecode($page);的语句,**直接删除或注释掉**(仅保留一次解码) - 在
checkPageValidity()函数开头增加截断逻辑:$page = strtok($page, '?');,防止?/etc/passwd类 payload - 确认
$target_blacklist数组包含'import.php'、'export.php'、'tbl_replace.php'等高危文件 - 白名单页面(如
db_sql.php)必须严格匹配完整文件名,禁止带.php?xxx后缀
强制所有 unserialize() 调用启用安全参数
4.9.x 中仍有多个 unserialize() 使用点(如 session 处理、导入模块),但均未使用 PHP 7.0+ 提供的 allowed_classes 选项。裸调用等于默认允许任意类反序列化。
立即学习“PHP免费学习笔记(深入)”;
- 全局搜索:
grep -r "unserialize(" --include="*.php" .,重点检查libraries/common.inc.php、import.php、libraries/core.lib.php - 将每个
unserialize($data)替换为:unserialize($data, ['allowed_classes' => false]) - 若某处必须反序列化特定类(极少见),显式列出白名单:
['allowed_classes' => ['PMA_Config', 'PMA_Message']] - 同时确保 PHP 配置中
unserialize_callback_func为空,避免回调函数被利用
真正麻烦的不是改几行代码,而是确认每处改动都生效且无遗漏——比如 unserialize() 可能藏在第三方插件或自定义脚本里,checkPageValidity() 可能在多个文件中被复制粘贴过。修复后务必用 index.php?target=db_sql.php%253f/../../../../etc/passwd 和 gis_data_editor.php?gis_data[gis_type]=%252e%252e%252fetc%252fpasswd 实测,别信“版本号看起来很新”这种错觉。



















