对 WordPress 站点而言,重点不是禁止访问 wp-content/uploads,而是确认其中哪些目录可由站点或插件写入、哪些请求会被 Nginx 转交给 PHP-FPM,再只阻断上传目录里的 PHP 解释路径。下面的清单适用于经授权维护的站点;变更前先备份配置,并准备好恢复原配置的路径。

1. 盘点可写目录和访问路径
先在站点服务器上确认 WordPress 实际目录、媒体目录及其 URL 映射。不要假设所有站点都使用默认路径:多站点、定制上传路径、符号链接或面板生成的配置,都可能改变实际位置。
在站点文件系统中检查目录:
cd /实际的/wordpress/目录
wp config get WP_CONTENT_DIR 2>/dev/null
find wp-content/uploads -maxdepth 3 -type d -print
find wp-content/uploads -type f ( -iname '*.php' -o -iname '*.phtml' -o -iname '*.phar' ) -print
若没有 WP-CLI,或该命令无法反映站点实际设置,应以站点配置和文件系统为准。对找到的可执行扩展名文件,先核实归属与用途;不要在未调查前直接删除。
在服务器上核对目录权限和写入主体:
namei -l /实际的/wordpress/目录/wp-content/uploads
find /实际的/wordpress/目录/wp-content/uploads -maxdepth 2 -type d -printf '%M %u:%g %pn'
确认 Web 服务、PHP-FPM 进程和部署任务分别以什么用户运行,以及哪些用户或进程确实需要写入。此处的目的,是识别风险范围,不是顺带递归修改整站权限。
| 盘点对象 | 要确认的内容 | 对业务的影响 |
|---|---|---|
uploads 及定制上传目录 | 实际文件路径、对应 URL、是否包含多站点子目录 | 媒体文件仍应可访问 |
| 写入主体 | PHP-FPM、部署任务或其他进程是否能写入 | 收紧写权限可能影响上传、缩略图或插件功能 |
| 上传目录内的脚本文件 | 是否存在 PHP 类扩展名文件,来源与用途是否明确 | 可能是历史遗留或插件产物,不应未经核实直接清理 |
| Nginx 站点配置 | 哪些 location 将 PHP 请求送到 FPM | 决定请求是否会进入解释器 |
2. 判断 Nginx 与 PHP-FPM 的执行路径
在 Nginx 服务器上查看实际加载配置,而不是只读某个文件中的片段:
sudo nginx -T 2>&1 | grep -nE 'server_name|root |alias |location|fastcgi_pass|SCRIPT_FILENAME'
重点找到对应站点的 server 块、上传目录的 root 或 alias 映射,以及将 PHP 请求转交给 PHP-FPM 的 location。fastcgi_pass 指向的 socket 或地址可以帮助确认请求的处理入口;如果配置由面板、容器或模板生成,应同时确认变更会写入哪个受管配置文件,避免修改后被覆盖。
Nginx 不是按配置文件从上到下简单决定所有 location。特别是常见的 PHP 正则匹配规则,可能会接管原本指向上传目录的请求。应核对实际 URI 与规则匹配结果,不能仅凭配置里“有一条禁止规则”就认定生效。
高风险情形包括:
- 上传目录中的
.php、.phtml等请求匹配到通用 PHP 规则,并被转交给 PHP-FPM。 - 禁止规则只覆盖默认的
/wp-content/uploads/,但站点实际使用了其他上传路径。 - 只检查目录浏览功能,却没有阻断已知文件路径上的 PHP 请求。
- 通过规则把 PHP 文件当静态文件返回。请求即使不再执行,也可能暴露脚本源码;验证时不能把“没有运行”当成足够的结果。
选择窄范围的阻断规则
常见做法是在站点的 server 块中添加专门匹配上传目录 PHP 类路径的正则 location,并将其放在通用 PHP-FPM 正则规则之前。例如:
location ~* ^/wp-content/uploads/.*.(php[0-9]*|phtml|phar)(/|$) {
deny all;
}
这条规则只示范默认上传 URL 路径。上线前要按站点的实际 URL 调整路径,并核实扩展名及路径信息写法是否覆盖了现有 PHP-FPM 规则接受的请求形式。正则 location 的先后顺序很重要:应确保上传目录的拒绝规则先于通用 PHP 处理规则,且没有其他规则重新接管请求。
不要将整个 WordPress 目录统一设为不可执行或禁止 PHP;WordPress 核心、主题和插件需要正常调用 PHP。也不要只因某项资料建议使用 ^~ /wp-content/uploads/ 就直接照搬:^~ 前缀匹配会影响后续正则 location 的选择,若配置不当,可能导致上传目录中的文件被当作静态内容返回。变更后必须用请求验证最终行为。
3. 小范围变更、备份和检查
先备份将要修改的 Nginx 配置,并记录原文件路径和当前生效配置。配置文件由面板或自动化工具管理时,应优先在对应的受管入口修改。
sudo cp -a /实际的/站点配置.conf /实际的/站点配置.conf.bak-$(date +%Y%m%d%H%M%S)
sudo nginx -T > /安全位置/nginx-before.txt 2>&1
建议先在测试站或单台灰度实例应用规则;如果无法灰度,选择低访问窗口并缩短观察周期。确认修改只作用于目标站点和上传路径,再检查语法:
sudo nginx -t
只有看到配置测试成功后,才重载 Nginx:
sudo systemctl reload nginx
重载 Nginx 通常不需要重启 PHP-FPM,但仍应观察服务状态和站点错误日志。若配置测试失败,不要重载;根据错误位置修复或恢复备份。
这项改动的预期影响是:正常图片、附件仍可由 Web 服务返回;直接请求上传目录中的 PHP 类文件应被拒绝,不再进入 PHP-FPM。若插件把可执行脚本放在上传目录并依赖访问该脚本,相关功能可能受影响,应先向插件维护方确认是否存在更安全的部署方式,不要为恢复功能而移除整条防护。
4. 验证图片、上传和 PHP 阻断
从有权限访问站点的客户端执行验证。先确认一张已知媒体文件仍正常返回:
curl -sS -o /dev/null -w '%{http_code} %{content_type}n'
'https://站点域名/wp-content/uploads/实际图片路径.jpg'
预期得到成功状态码和相应的图片内容类型。再通过 WordPress 后台上传一张无害测试图片,确认上传成功、媒体库能显示图片;如果站点使用缩略图或相关插件,也要走一遍对应业务流程。
验证 PHP 阻断时,优先在测试站点操作。确需在生产站点验证,应限制测试文件的存放与访问范围、使用无害内容,并在测试后立即删除。不要使用会读取系统信息、执行命令或修改数据的测试代码。若文件放错位置或规则未生效,脚本可能被 PHP-FPM 执行,或被当作静态内容泄露源码。
验证结果应满足以下条件:
- 请求上传目录中的测试 PHP 文件返回拒绝访问或不存在;具体状态码取决于站点规则。
- 响应正文既没有测试脚本的执行输出,也没有 PHP 源码。
- Web 与 PHP-FPM 日志中没有该测试请求被送入应用执行的证据。
- 正常图片访问、后台媒体上传、登录和相关插件流程仍正常。

5. 观察日志并处理异常
在变更后的观察窗口内,检查 Nginx 访问日志和错误日志;若站点记录 PHP-FPM 日志,也核对相关时间段。具体日志路径以当前虚拟主机配置为准:
sudo tail -n 100 /实际的/站点/access.log
sudo tail -n 100 /实际的/站点/error.log
关注上传目录请求是否返回预期拒绝结果、图片请求是否正常,以及是否出现插件访问脚本被拒绝、上游错误或新的 404。日志中出现拒绝记录不一定代表攻击;应结合请求来源、路径、时间和业务操作判断。若错误集中在某个插件访问路径,先确认它是否确实需要在上传目录执行 PHP,再决定如何调整,而不是扩大通用 PHP 规则的放行范围。
6. 回滚与复盘
如果图片、上传或插件功能出现无法接受的影响,或日志显示规则匹配范围错误,应先恢复变更前配置,再检查语法并重载:
sudo cp -a /实际的/站点配置.conf.bak-时间戳 /实际的/站点配置.conf
sudo nginx -t && sudo systemctl reload nginx
回滚后重新验证图片访问、后台上传和相关功能,并记录恢复时间与故障现象。回滚只是恢复服务,不代表风险已经解决;应保留配置差异、请求样例、日志证据和未解决的插件依赖,安排后续用更窄的匹配规则重新验证。
变更完成后,复盘清单至少应记录:实际受保护的 URL 和文件路径、PHP-FPM 入口规则、配置备份位置、语法检查结果、图片与上传验证结果、观察窗口内的异常,以及回滚责任人和操作路径。这样后续维护者才能复核防护是否仍覆盖当前站点,而不会误将一次配置修改当作长期有效的保证。

广东省深圳市 1F
清单很实用,正好在搞这个事