适用对象:在虚拟主机/共用服务器或 VPS 上,把多个站点部署到公开目录(public/、public_html/、htdocs/ 等)来运维的人。这里不讲攻击手法,只讲盘点自己的服务器并把洞堵上。.env 本身的防护方法,另请参阅 共用服务器上的 .env 保护。
本站的视角:『放在哪里』本身就是访问控制
密钥泄露的原因,比起高深的攻击,更多是放错位置的事故。webroot 是『任何人都能通过 URL 来取的地方』。一旦把密钥放进那里,服务器的密码再强也毫无意义。本站以密钥既不放进 webroot 也不放进 git 作为根基(→ 密钥的安全保管)。思路很简单:「公开目录=公开货架」。货架上只放被人看到也无所谓的东西。
public/ = 任何人都可通过 URL 取走
可以放
图片·CSS·JS 等公开资源
不要放
.env·token.json·.sql·.git·.bak
应用根目录之上 = 不会被分发
放在这里
密钥·令牌·认证凭据·备份。权限 600(仅所有者可读)。无法从 URL 到达。
为什么会发生「公开目录里的遗忘」
实际常见的情形是:为图方便而放的文件,或是样板里一开始就带着的文件,就这样被持续公开下去。
例如,为对接外部服务而制作的含访问令牌的 JSON,被放在 public/ 之下并长期搁置——而且如果它源自共用模板,同一个文件会被复制到多个站点的同一位置,全部都带着同一个洞。即便修好了一个站点,只要其他站点还开着,也毫无意义。同样危险的,还有 .env、数据库备份(.sql)、.git 目录、编辑器备份(*.bak)、快捷方式等的遗忘(相关:路径穿越·.env 被整个公开的事)。
盘点自己的服务器
首先机械地排查「自己的公开目录里有没有看起来像密钥的文件」。这是对自己资产的排查,而不是窥探他人站点的行为。
搜索公开目录之下看似密钥的文件
public/ 等处的密钥候选(令牌/认证凭据的 JSON、.env、密钥、快捷方式)。以横向扩散为前提扩展到『全机·全站点』
逐一判断是否真的需要公开
# 盘点自己服务器的公开目录之下(对自己资产的排查)
find ~ -path '*/public/*' \( -iname '*token*.json' -o -iname '*credential*.json' \
-o -iname '*.bak' -o -iname '*.sql' -o -iname '.env*' \) 2>/dev/null
# .git 目录被公开同样危险
find ~ -path '*/public/*/.git' -maxdepth 8 2>/dev/null发现时的处理
发现后,要把移除·吊销·迁移这三点成套执行。缺少任何一点都堵不彻底。
从 webroot 移除,使其无法通过 URL 取走
可能已泄露的密钥·令牌要吊销/重新签发
把密钥放到 webroot 之外+权限 600
容易犯的放置方式(危险)
- 把对接用令牌的 JSON 放进
public/ - 把样板里带着的密钥文件就这样公开
- 把备份(
.sql/.bak)或.git放任在公开目录之下 - 只修一个站点就『处理完毕』
正确的放置方式
- 公开目录里只放可以公开的东西
- 密钥放在 webroot 之外+权限 600
- 敏感扩展名拒绝分发(在配置中 deny)
- 一处发现就盘点全机·全站点
把『只放可以公开的东西』定为运维规则
比起逐个应对,把它规则化更有效。把公开目录=公开货架定下来,密钥·备份·版本管理数据(.git)·配置文件原则上都不放在那里。更新样板(模板)时,要从样板侧抽掉密钥——否则,同一个洞会继续被复制到下次批量生产的站点里。
本站是怎么做的
本站以密钥(密钥·令牌·连接信息)既不放进公开目录也不放进代码仓库作为根基。纳入部署产物的只有构建完成的公开资源,密钥则作为运行环境的环境变量,保存在不会被分发的地方。理由是,本文这一类事故是「一处遗忘,一发 URL 全部泄露」的典型。我们把放置位置本身设计成访问控制,并把盘点与 漏洞应对的盘点 放在同一时机一起做。
接下来阅读
- 按技术:共用服务器上的 .env 保护 / 漏洞应对实务(盘点)
- 术语:.env 文件与密钥信息 / 路径穿越
- 事故:.env 被整个公开的事
- 保管:密钥的安全保管
FAQ
Q把文件放在公开目录里有什么危险?
放进 Web 公开目录(webroot=public/ 或 public_html/ 等)的文件,只要直接访问 URL 任何人都能取走。令牌、认证凭据的 JSON、.env、备份、密钥文件等一旦遗忘在那里,会在无人察觉之间被取走,立刻演变成实害。原则是:公开目录里只放『可以公开的东西』。
Q如果在一个站点发现了,是否应该排查其他站点?
应该。当你用共用模板或样板批量生产站点时,同样的遗忘往往已经横向扩散到了所有站点。一处发现,就要对源自同一模板的全部站点、全部主机一并排查。
Q发现之后该如何处理?
①把相关文件从 webroot 移除,使其无法通过 URL 取走(变成 404);②可能已泄露的令牌、密钥要刷新/吊销(按已泄露来处理);③今后把密钥放在 webroot 之外,并把权限设为 600(仅所有者可读)。这三点要成套执行。