首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 臨時文件安全深度指南:風險分析、攻擊向量與防禦體系

     編輯:PHP 相關知識

臨時文件分類與分布

類型典型路徑生命週期風險等級
上傳文件/tmp/phpXXXXXX請求結束自動刪除🔴 高
Session 文件/var/lib/php/sess_GC 清理 (默認 24 分鐘)🔴 高
緩存/中間文件/tmp/app_*, /dev/shm/業務邏輯控制🟡 中
編輯器備份~/.*swp, .bak手動/編輯器管理🟢 低

核心安全特徵與風險

1. 可見性風險 (信息洩露)

  • 多用戶共享 /tmp,權限通常 1777 (sticky bit),僅防刪除,**不防讀取**
  • 敏感數據 (SQL 結果、API Key、用戶隱私) 寫入臨時文件可被同機用戶讀取
  • 可預測文件名 (如 spellcheck46) 導致遍歷讀取他人數據

2. 可執行性風險 (代碼執行)

  • 攻擊者上傳 .php 到 /tmp,若 Web 根目錄配置不當或包含漏洞,可觸發執行
  • include '/tmp/upload_123.php'; 類邏輯極度危險

3. 劫持/競爭條件 (TOCTOU)

  • 創建-寫入間隙:tempnam() 返回名稱到 fopen() 之間,攻擊者可建立同名符號鏈接指向敏感文件
  • 內容篡改:寫入後、讀取前,攻擊者修改內容 (注入惡意數據、追加代碼)
  • 刪除/重命名:導致業務邏輯異常、拒絕服務

4. 持久化風險 (殘留文件)

  • 進程崩潰、OOM Kill、磁盤滿、邏輯漏洞導致未清理
  • 殘留文件積累佔用磁盤、洩露歷史數據、成為入侵痕跡

防禦體系:分層纵深

第 1 層:不可預測的文件名



第 2 層:最小權限創建

$fp = fopen($tempName, 'c+b'); // 創建/打開二進制讀寫,不截斷
if ($fp) {
    // 立即設置權限 0600 (僅擁有者讀寫)
    fchmod($fp, 0600);
    // 可選:獲取文件描述符傳遞給子進程,避免路徑暴露
}

第 3 層:寫入前驗證空文件 (防劫持)

if (filesize($tempName) !== 0) {
    // 文件非空,可能被搶佔
    unlink($tempName);
    throw new RuntimeException('Temp file hijacked');
}
fwrite($fp, $data);

第 4 層:完整性校驗 (防篡改)

// 寫入後計算哈希存入 Session/Redis
$hash = hash_file('sha256', $tempName);
$_SESSION['temp_hash'][$tempName] = $hash;

// 後續讀取前驗證
if (hash_file('sha256', $tempName) !== $_SESSION['temp_hash'][$tempName]) {
    throw new RuntimeException('Temp file tampered');
}

第 5 層:上傳文件專用驗證

// ✅ 必須使用 is_uploaded_file + move_uploaded_file
$tmpName = $_FILES['avatar']['tmp_name'];
if (!is_uploaded_file($tmpName)) {
    die('Invalid upload');
}
// 移動到業務目錄 (跨分區複製+刪除,原子性更好)
$dest = '/var/www/uploads/' . bin2hex(random_bytes(16)) . '.png';
if (!move_uploaded_file($tmpName, $dest)) {
    die('Move failed');
}
// 設置權限
chmod($dest, 0644);

第 6 層:系統級加固

  • 獨立 tmpfs:為 PHP-FPM 池配置 php_admin_value[upload_tmp_dir] = /var/www/tmp_pool1,掛載 noexec,nosuid,nodev 的 tmpfs
  • open_basedir:限制腳本訪問路徑 open_basedir = /var/www:/tmp/php_session
  • 定期清理:Systemd Timer / Cron 清理超時臨時文件
  • 審計日誌:auditd 監控 /tmp 敏感操作

最佳實踐清單

  1. 盡量**不落盤**:用內存數組、Redis、共享內存 (shmop) 替代臨時文件
  2. 必須落盤:sys_get_temp_dir() + random_bytes() + 0600 權限
  3. 寫入前驗證大小為 0,寫入後立即哈希
  4. 上傳文件**只用** is_uploaded_file + move_uploaded_file
  5. 業務結束**立即 unlink**,註冊 register_shutdown_function 兜底清理
  6. 定期掃描代碼庫:grep -r "tempnam\|tmpfile\|sys_get_temp_dir" --include="*.php"

臨時文件雖小,牽一髮而動全身。將「不信任文件系統」原則貫穿始終,構建零信任的臨時文件處理流程。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved