allow_url_include 與 allow_url_fopen 是 PHP 遠程文件包含漏洞的「雙子星」。早期安全建議禁用 allow_url_fopen,但這會破壞大量合法業務(如 API 調用、遠程配置拉取)。PHP 5.2.0 引入 allow_url_include 專門控制 include/require 的遠程協議支持,成為更精準的防護開關。
攻擊者可通過 Session 文件、上傳文件、日誌注入、/proc/self/environ 等途徑將惡意代碼寫入本地文件,再利用 include $userInput 執行。遠程協議禁用不影響本地包含。
即使 allow_url_include=Off、allow_url_fopen=Off,以下協議仍可被 include 使用:
<?php
// 攻擊向量 1:直接包含 POST 原始數據
include "php://input"; // 攻擊者 POST
// 攻擊向量 2:data 協議嵌入 Base64 Payload
include "data:;base64,PD9waHAgc3lzdGVtKCdscycpOz8+"; // 解碼後為
?>
這些協議不屬於「URL 協議」,不受上述兩個 INI 選項限制。
// ❌ 極度危險
include $_GET['page'] . '.php';
// ✅ 白名單機制
$allowed = ['home', 'about', 'contact', 'dashboard'];
$page = $_GET['page'] ?? 'home';
if (in_array($page, $allowed, true)) {
include __DIR__ . "/pages/{$page}.php";
} else {
include __DIR__ . '/pages/404.php';
}
; php.ini
disable_functions = "exec,system,passthru,shell_exec,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source"
; 關鍵:禁用 stream_wrapper 註冊(需 Suhosin 或 PHP 7.4+ 特定補丁)
; suhosin.executor.include.whitelist = "phar" // 僅允許 phar 協議
include 白名單、加密 Cookie、限制請求參數等。; php.ini
open_basedir = /var/www/html:/tmp:/usr/share/php
結合 Docker/K8s 容器化部署,掛載只讀代碼卷,臨時目錄掛載 noexec、nosuid,徹底切斷寫入執行鏈。
allow_url_include=Off 是必要的基線配置,但絕非充分條件。真正的防禦體系需覆蓋:代碼審計消除動態包含 → 禁用危險函數/協議 → 部署安全擴展 → 系統級隔離。每一層都能獨立攔截攻擊,組合起來才能構建韌性防線。