首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

常見 SQL 注入攻擊手法總結與防禦對策

     編輯:PHP 相關知識

前言

SQL 注入 是 Web 應用最嚴重的安全威脅之一。本文系統梳理 7 大類經典注入手法,分析原理與實例,並給出針對性防禦方案。

七大類注入攻擊手法

1. 未正確過濾轉義字符(經典注入)

原理: 用戶輸入直接拼接進 SQL 字符串,單引號閉合前級查詢,注入任意邏輯。

脆弱代碼:

"SELECT * FROM users WHERE name = '" + userName + "';"

攻擊載荷:

輸入:a' OR 't'='t
SQL:SELECT * FROM users WHERE name = 'a' OR 't'='t';  -- 恆真,繞過認證

多語句注入(支持批量查詢的 DB):

輸入:a'; DROP TABLE users; SELECT * FROM data WHERE name LIKE '%
SQL:SELECT * FROM users WHERE name = 'a'; DROP TABLE users; SELECT * FROM data WHERE name LIKE '%';

2. 類型處理不當

原理: 數值型參數未驗證類型,直接拼接,攻擊者傳入 SQL 片段而非數字。

脆弱代碼:

"SELECT * FROM data WHERE id = " + a_variable + ";"

攻擊載荷:

輸入:1; DROP TABLE users
SQL:SELECT * FROM data WHERE id = 1; DROP TABLE users;

3. 數據庫服務器漏洞

案例: MySQL mysql_real_escape_string() 在特定字符集(如 GBK)下編碼繞過漏洞(CVE-2008-2079)。

防禦: 及時更新數據庫版本,使用預處理語句繞過驅動層轉義邏輯。

4. 盲目 SQL 注入

原理: 頁面不直接回顯數據或錯誤,但根據邏輯判斷結果返回不同內容(如「文章存在」vs「不存在」)。

攻擊過程: 逐位暴力猜解數據(如密碼雜湊),極其耗時。工具 sqlmap、Absinthe 可自動化利用。

5. 條件響應注入

原理: 構造邏輯判斷,觀察頁面差異。

正常:SELECT * FROM books WHERE id = 'OOk14cd' AND 1=1  -- 返回內容
注入:SELECT * FROM books WHERE id = 'OOk14cd' AND 1=2  -- 返回空/不同內容
→ 證明注入存在,可進一步構造子查詢竊取數據

6. 條件錯誤注入

原理: 強制數據庫在條件為真時產生錯誤,通過錯誤回顯提取信息。

SELECT 1/0 FROM users WHERE username='Ralph'  -- 若用戶存在,除零錯誤
SELECT CASE WHEN (SELECT 1 FROM users WHERE username='admin') THEN 1/0 ELSE 1 END  -- 通過錯誤判斷用戶存在

7. 時間延遲注入

原理: 利用 SLEEP()、BENCHMARK() 等函數,根據條件真偽延遲響應,通過測量時間差推斷信息。

MySQL: SELECT IF(1=1, SLEEP(5), 0)  -- 5秒延遲
PostgreSQL: SELECT pg_sleep(5)
SQL Server: WAITFOR DELAY '0:0:5'
Oracle: DBMS_PIPE.RECEIVE_MESSAGE('a',5)

進階威脅:自動化攻擊工具與僵尸網絡

現代攻擊高度自動化:

  • sqlmap:全自動檢測、利用、數據提取
  • Asprox Trojan:僵尸網絡掃描 ASP 網站,批量注入惡意 JS,植入駭客程序
  • 掃描器:大規模指紋識別 + 注入探測

經典繞過登錄案例

查詢:SELECT * FROM users WHERE username = '{username}' AND password = '{password}'

輸入密碼:' OR ''='
結果:SELECT * FROM users WHERE username = 'anyuser' AND password = '' OR ''=''
→ 條件恆真,返回首行用戶(通常是管理員)

PHP 防禦最佳實踐

核心方案:預處理語句

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
]);

$stmt = $pdo->prepare('SELECT * FROM users WHERE username = ? AND password = ?');
$stmt->execute([$_POST['username'], $_POST['password']]); // 密碼應為雜湊值驗證
$user = $stmt->fetch();
?>

舊代碼遷移輔助函數(僅作過渡)

<?php
function quote_smart($value, PDO $pdo): string {
    // 1. 若開啟 magic_quotes_gpc(PHP<5.4),先去轉義
    if (get_magic_quotes_gpc()) {
        $value = stripslashes($value);
    }
    // 2. 非數值類型,使用驅動層真實轉義並加引號
    if (!is_numeric($value)) {
        return "'" . $pdo->quote($value) . "'"; // PDO::quote 內部調用 mysql_real_escape_string
    }
    return $value;
}

// 使用示例(僅用於無法立即改造的舊代碼)
$sql = "SELECT * FROM users WHERE id = " . quote_smart($_GET['id'], $pdo);
?>

⚠️ 注意: quote_smart 自動加引號,調用時勿重複添加。遠程連接必須傳入 PDO 實例作為第二參數。

多層防禦體系

層級措施說明
代碼層全面使用預處理語句徹底分離代碼與數據,根治注入
代碼層嚴格輸入驗證(類型、長度、格式、白名單)業務邏輯約束,減少攻擊面
數據庫層最小權限賬號Web 賬號僅擁有必要表的增刪改查
數據庫層禁用多語句執行PDO::MYSQL_ATTR_MULTI_STATEMENTS = false
網絡層WAF(Web 應用防火牆)識別攔截常見攻擊特征,纵深防禦
監控層SQL 審計日誌 + 異常告警事後追蹤,發現 0day 利用
開發層代碼審計 + SAST 掃描上線前發現漏洞

總結

SQL 注入本質是**代碼與數據未分離**。無論攻擊手法如何變換(聯合查詢、盲注、報錯、延遲),**預處理語句**始終是根本解決方案。輔以嚴格輸入驗證、最小權限、WAF 纵深防禦,可將風險降至最低。開發團隊應建立「無預處理不提交」的工程規範,定期掃描歷史代碼遷移。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved