必须在PHP层防护会话固定:登录成功后立即调用session_regenerate_id(true),并启用php.ini中session.use_strict_mode=1、session.cookie_httponly=1和session.cookie_secure=1(HTTPS下),phpMyAdmin本身不处理该防护。
phpMyAdmin本身不处理会话固定防护,责任在PHP层
phpmyadmin 是纯前端代理,它不生成、不校验、也不重置会话 id。所有 session 行为由底层 php 运行时控制。因此,防会话固定攻击不能靠改 phpmyadmin 配置,而必须确保 php 的 session_start() 和 session_regenerate_id(true) 正确介入登录流程。
登录成功后必须调用 session_regenerate_id(true)
phpMyAdmin 的登录逻辑(libraries/auth/cookie.auth.lib.php 或 libraries/auth/http.auth.lib.php)里,认证通过后若没执行该函数,攻击者可提前分发 PHPSESSID 并坐等用户登录——一旦命中,直接接管会话。
- ✅ 正确做法:在认证成功、写入
$_SESSION['user']后立即调用session_regenerate_id(true) - ❌ 常见错误:只调用
session_regenerate_id()(缺true参数),旧 session 文件仍存在,攻击者可继续读取 - ⚠️ 注意:
session_regenerate_id(true)必须在session_start()之后、任何输出之前执行;否则会触发 “headers already sent” 错误
配合 php.ini 强制启用严格模式
仅靠代码再生还不够。PHP 默认允许使用任意字符串作为 session ID,攻击者可构造有效但非法的 ID 绕过验证。开启 session.use_strict_mode = 1 能让 PHP 拒绝所有未由自身生成的 ID,从协议层堵住漏洞。
审查 Remix v2 代码中的 v1 形态 meta 导出(v2 中为破坏性变更),cookie 安全漏洞(httpOnly、secure、密钥轮换),认证门位于错误层级,以及其他
- ✅ 在
/etc/php/*/apache2/php.ini或/etc/php/*/fpm/php.ini中设:session.use_strict_mode = 1 - ✅ 同时建议启用:
session.cookie_httponly = 1和session.cookie_secure = 1(后者需 HTTPS) - ⚠️ 若已存在大量旧 session 文件,重启 PHP 服务后首次访问可能报错“session_start(): Failed to read session data”,属正常现象,旧无效 ID 会被自动丢弃
别依赖 phpMyAdmin 的“禁用书签”或“改目录名”来防会话固定
书签功能、URL 路径、界面开关这些和会话 ID 生命周期完全无关。会话固定攻击发生在 HTTP 请求头层面(Cookie 或 URL 参数),跟 phpMyAdmin 是否显示“SQL”标签页、是否删了 pma__bookmark 表毫无关系。
- ❌ 禁用书签、隐藏菜单、改
$cfg['blowfish_secret']都不能阻止攻击者传递并复用 session ID - ✅ 真正有效的防线只有两条:登录后强制再生 ID + PHP 层启用 strict mode
- ⚠️ 最容易被忽略的是:很多自定义 auth 插件或二次开发版本,悄悄绕过了标准登录流程,导致
session_regenerate_id(true)根本没被执行


















