必须禁止web访问application/、runtime/、config/等目录,因其含敏感配置、日志、缓存及可能的明文密码;public/是唯一应被documentroot指向的目录,其余均为后端私有区域。

ThinkPHP 项目根目录下哪些文件必须禁止 Web 访问
直接暴露 application/、runtime/、config/ 这些目录,等于把配置、日志、缓存全扔给爬虫和攻击者。尤其 runtime/ 里可能有数据库密码明文缓存(取决于驱动和配置),config/ 下若误存了 .env 或未被 .gitignore 排除的敏感配置,风险极高。
关键不是“能不能访问”,而是“有没有必要通过 HTTP 访问”——答案是否定的。所有非公开资源都该挡在 Web 服务器之外。
-
application/:包含控制器、模型、配置,PHP 源码本身不执行,但源码泄露可辅助漏洞利用 -
runtime/:运行时生成的缓存、日志、模板编译文件,部分日志含 SQL 或用户输入原文 -
extend/和vendor/下的某些测试或示例文件(如vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php)曾被用于 RCE -
public/是唯一应被 Web 服务器 DocumentRoot 指向的目录;其余全部属于“后端私有区域”
Apache 下用 .htaccess 禁止目录遍历最简写法
别信网上抄来的“全站 deny from all”,ThinkPHP 的 public/ 目录必须能被访问,否则 CSS/JS/图片全 404。真正要拦的是 public/ 同级的所有兄弟目录。
在项目根目录(即 public/ 所在目录)放一个 .htaccess,内容只写三行:
<ifmodule mod_rewrite.c>
RewriteEngine off
</ifmodule>
Order Deny,Allow
Deny from all
注意:RewriteEngine off 是必须的。ThinkPHP 自带的重写规则在 public/.htaccess 里,根目录若开启重写,可能干扰路由或导致 500 错误。
- 不要用
<directory></directory>块——虚拟主机环境下通常无权限 - 不要写
Require all denied(Apache 2.4+ 语法),老版本 Apache 2.2 会直接 500 - 确认服务器启用了
mod_authz_core和mod_access_compat,否则Deny from all不生效
Nginx 下 location 匹配路径时的常见漏网之鱼
Nginx 没有 .htaccess,必须改 server{} 配置。最容易漏的是以点开头的文件(如 .env、.git/config)和斜杠结尾的路径(如 /runtime/ vs /runtime)。
在 server 块里加这几段,放在 location / 之前:
location ~* ^/(application|runtime|extend|vendor|config|common|tests|\.env|\.git|\.svn|\.idea) {
deny all;
}
- 正则末尾没加
$,所以/runtime/和/runtime/test.php都会被匹配 -
~*表示忽略大小写,防有人试/RUNTIME/ - 务必把这段放在
location /和 ThinkPHP 的重写规则之前,否则会被 proxy_pass 或 fastcgi_pass 覆盖 - 如果用了 Docker,检查 Nginx 配置是否挂载进容器,且 reload 成功(
nginx -t && nginx -s reload)
TP5/TP6 中 public/index.php 入口文件的隐藏陷阱
很多人以为只要把入口文件挪到 Web 根目录就安全了,其实不然。ThinkPHP 默认允许通过 index.php?s=/xxx 方式访问,而这个 index.php 若没做额外限制,本身就是个“合法入口”。更危险的是,有些部署会把整个 ThinkPHP 目录放到 Web 可访问路径下,靠 public/ 作软链接——软链接一旦失效,index.php 就可能从错误路径加载框架,暴露出错信息里的绝对路径。
- 确保
public/index.php中define('APP_PATH', __DIR__ . '/../application/');的路径是相对且稳定的 - 禁用调试模式上线:确认
app_debug为false,否则异常堆栈会打印完整路径 - 检查
public/目录下是否残留了index.php.bak、phpinfo.php等测试文件——它们不受任何框架逻辑保护 - 用 curl 测试:
curl -I https://yoursite.com/runtime/应返回 403,而不是 200 或 404(404 说明没拦住,只是文件不存在)
路径保护不是一次性配置,而是每次部署、升级、加新模块时都要重新核对的底线动作。尤其是引入第三方扩展包时,它们自带的 public/ 或 docs/ 目录,常常悄悄绕过你的防护逻辑。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











