Nginx 敏感文件泄露防护实战:拦截 .git 与 .env

敏感文件泄露防护是 Web 安全中最容易被忽视的环节:攻击者通过批量扫描 /.git/config/.env/backup.zip 等常见路径,一旦命中即可获取完整源码或数据库凭据,进而实现接管。本文基于 Nginx 给出一套完整的敏感文件拦截配置,包含验证方法与泄露后的应急处理。

适用场景

  • 站点目录由 Git 管理,部署时 .git 目录随之发布到 Web 根目录
  • 项目根目录残留 .envconfig.php.bak*.sql 等开发调试文件
  • 运维人员习惯将备份压缩包临时放在 Web 根目录下
  • 网站上线前做安全基线检查,需统一收敛文件暴露面

前置条件

  • Nginx 1.x,具备配置文件修改与重载权限
  • 清楚站点的 server 块配置文件位置
  • 本地有 curl 或浏览器用于验证

原理说明

自动化扫描器会批量探测以下高危路径,命中任何一个都可能导致严重后果:

  • /.git/HEAD/.git/config:使用 git-dumper 等工具可完整还原源码仓库,包括历史提交中误提交的密码与 API Key
  • /.env:Laravel 等框架的环境配置文件,通常包含数据库、Redis、邮件服务凭据
  • *.sql*.bak*.zip:数据库导出与代码备份,直接下载数据
  • /.svn/entries:SVN 版本信息泄露
  • /phpinfo.php:暴露服务器路径、扩展、环境变量等敏感信息

防护思路是在 Nginx 层直接拒绝访问,即使文件真实存在,攻击者也无法读取。返回 404 而非 403,可避免向扫描器确认目标存在。

操作步骤

1. 拦截隐藏目录与版本控制目录

在站点 server 块中加入以下配置。注意使用 (?!well-known) 负向断言保留 /.well-known/ 路径,否则会阻断 Let’s Encrypt 证书验证:

location ~ /\.(?!well-known) {
    deny all;
    return 404;
}

2. 拦截高危后缀与备份文件

location ~* \.(env|sql|bak|old|swp|conf|ini|tar|gz|tgz|zip|7z|rar)$ {
    deny all;
    return 404;
}

若站点存在正常的压缩包下载业务,将该规则改为仅拦截 Web 根目录下的文件,并对下载目录单独放行:

location ~* ^/downloads/.*\.(zip|tar\.gz)$ {
    allow all;
}

location ~* \.(env|sql|bak|old|swp|conf|ini|tar|tgz|zip|7z|rar)$ {
    deny all;
    return 404;
}

Nginx 的 location 正则匹配按顺序生效,放行规则必须写在前面。

3. 关闭目录列举

确认未开启自动索引,防止目录结构直接暴露:

autoindex off;

4. 限制上传目录的 PHP 执行

顺手加固:上传目录不允许执行 PHP,阻断 WebShell 落地后的直接利用:

location ~* ^/(uploads|files)/.*\.php$ {
    deny all;
}

5. 重载配置

nginx -t && systemctl reload nginx

配置验证

依次请求以下路径,预期全部返回 404

curl -I https://www.example.com/.env
curl -I https://www.example.com/.git/config
curl -I https://www.example.com/db_backup.sql
curl -I https://www.example.com/site.zip

同时验证 /.well-known/ 未被误伤(证书续期依赖):

curl -I https://www.example.com/.well-known/acme-challenge/test

常见问题

FAQ 1:拦截 .zip 后影响正常下载怎么办?

按照步骤 2 的方式,用更精确的 location 将下载目录(如 /downloads/)单独放行,并确保放行规则写在拦截规则之前;或者拦截规则只匹配 ^(?!/downloads/) 开头的路径。业务文件建议存储到对象存储而非 Web 根目录,从根本上避免误伤。

FAQ 2:文件已经被扫描下载过,如何补救?

首先确认暴露时间:在访问日志中检索扫描痕迹:grep -E '\.(env|git|sql|bak)' /var/log/nginx/access.log。然后执行应急三步:① 立即轮换全部泄露凭据,包括数据库密码、Redis 密码、第三方 API Key、邮件授权码;② 若 .git 被访问,历史提交一律视为已泄露,使用 BFG Repo-Cleaner 清理敏感文件后重置所有凭据;③ 物理删除 Web 根目录中的 .env、备份包等文件,配置仅是兜底而非根治。

总结

敏感文件泄露属于典型的低成本高危漏洞:攻击成本几乎为零,命中后可直接接管站点。Nginx 层拦截配置一次部署长期有效,但必须配合源头治理——版本控制目录不发布到生产环境、备份文件不落 Web 根目录、凭据定期轮换。建议将上述 curl 验证命令纳入上线检查清单。