Papa Labs

给老 Drupal 站补 Host Header 防护,却先跟 cPanel 的文件锁打了两回合

公司一个还跑在 Drupal 9.1.5 + PHP 7.4 上的老官网,管理后台的状态报告里常年亮着一条安全警告:Trusted Host Settings 未配置。这条警告平时很容易被当成”又一条黄色小字”划过去,但它背后对应的是一类真实的攻击面——HTTP Host Header 欺骗(Host Header Spoofing)

这条警告到底在防什么

浏览器访问网站时,HTTP 请求里会带一个 Host 头,告诉服务器”我要找的是哪个站点”——因为一台服务器上往往托管着很多个网站,服务器靠这个头来分发请求。问题在于:很多 Web 应用会无条件信任这个头的内容,而它是客户端随便就能伪造的。

攻击者直接对着服务器 IP 发请求,把 Host 头改成自己控制的域名,如果 Drupal 没有配置”可信主机列表”,它就会把伪造的域名当成自己的域名来用。由此衍生出两类经典攻击:

  • 密码重置投毒:攻击者对管理员账号触发”忘记密码”,Drupal 用伪造的 Host 头生成重置链接——管理员收到的邮件里,重置链接指向的是攻击者的域名,一点击,重置 token 就送出去了;
  • 缓存投毒:带伪造 Host 头的请求被 Drupal 缓存后,正常访客拿到的页面里,内部链接全部指向攻击者的服务器。

修复方式很便宜:在 settings.php 末尾加一段 trusted_host_patterns,白名单列出自己的域名。此后任何 Host 头对不上白名单的请求,Drupal 直接回 400 拒绝。

真正费劲的部分:文件被锁了两层

配置本身两分钟就能写完,但这台站点托管在 cPanel 上,编辑过程结结实实撞了两次墙。

第一层锁:文件本身是 0444。 Drupal 出于安全考虑,默认把 settings.php 的权限设成只读(0444)。cPanel 文件管理器里直接点编辑,保存时会被拒绝。解法:先把文件权限临时改成 0644,放开属主的写权限。

第二层锁:所在目录也是锁的。 权限改完再编辑,保存时又报错——

The system failed to create the file ”…/sites/default/settings.php.lock” … Permission denied

cPanel 的在线编辑器保存文件前,会在同目录下创建一个临时的 .lock 文件来防止并发编辑。而 Drupal 不止锁了 settings.php连它所在的 sites/default 目录也锁成了 0555(只读+执行)——编辑器连锁文件都写不进去。解法:把 sites/default 目录临时改成 0755,这次保存立刻成功。

Drupal 对 settings.php 的保护是两层的:文件本身 0444,所在目录 0555——cPanel 编辑器保存时要在目录里写临时锁文件,两层都要临时放开

改完配置之后,两层权限都要记得锁回去

改完之后的收尾同样重要:目录改回 0555、文件改回 0444,把 Drupal 的保护恢复原样。最后刷新状态报告页面,那条常年亮着的警告变成了绿色对勾。

顺手确认的坏消息

处理这条警告时顺手核对了版本状态,结论不太乐观:

  • Drupal 9 已于 2023 年 11 月停止支持——这个站点两年多没有收到过任何安全补丁;
  • PHP 7.4 更早,2022 年 11 月就停止安全支持了
  • 从 9.1 升到当前的 Drupal 11 没有”一键升级”,必须先过渡到 10、处理废弃 API,是一个完整的迁移项目。

trusted_host_patterns 这一手只是把一个明确的、便宜的漏洞先堵上;真正的解药是立项迁移。

教训

  1. 状态报告里的安全警告值得逐条问一句”它在防什么”——“Trusted Host Settings 未配置”听起来抽象,展开看对应的是密码重置投毒和缓存投毒两类具体攻击,而修复只要几行配置;
  2. Drupal 的文件加固是两层的:文件权限 + 目录权限——在线编辑器(cPanel 这类)保存文件时通常要在同目录写临时文件,只放开文件本身的写权限是不够的;
  3. 临时放开的权限一定要当场锁回去——0444/0555 是 Drupal 刻意的安全设计,改完配置就恢复,不要留到”以后再说”;
  4. EOL 的 CMS 和 PHP 版本,修一条警告改变不了大局——记下来、立项、排期迁移,别让绿色对勾制造安全错觉。
← 全部文章