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

SQL 注入攻擊原理與防禦實戰:從駭客視角理解風險

     編輯:關於SqlServer

⚠️ 安全聲明

本文旨在**防禦教育**,展示攻擊原理以便開發者理解風險並建立防護。**嚴禁**將此資訊用於未授權系統測試或攻擊。所有程式碼範例已去武器化,僅保留教學骨架。

經典注入點分析

原始碼片段 (PHP + MySQL) 展示兩個模組的脆弱模式:

1. Members_List 模組:字串拼接 + 無參數化


$where = "where uname != 'Anonymous' ";
if ($letter != "Other" && $letter != "All") {
    $where .= "AND uname LIKE '" . $letter . "%' ";  // 直接拼接使用者輸入
}
$sort = "ORDER BY $sortby";  // 欄位名同樣拼接
$limit = " ASC LIMIT $min, $max";  // 數值參數未驗證
$result = sql_query($select . $where . $sort . $limit, $dbi);

攻擊向量:letter、sortby、min/max 皆可注入。若 magic_quotes_gpc=OFF,單引號不被轉義,攻擊者可構造:

  • letter = ' OR '1'='1 → 繞過過濾,列出所有用戶。
  • sortby = UserID; DROP TABLE users; -- → 多語句執行 (視驅動程式支援)。
  • min = 0; UPDATE users SET pass='hacked' WHERE uid=1; -- → 資料竄改。

2. Your_Account 模組:參數直接帶入 SQL


case "login":
    login($uname, $pass);  // 內部可能直接拼接
function login($uname, $pass) {
    $sql = "SELECT * FROM users WHERE uname='$uname' AND pass='$pass'";
}

經典繞過:uname = ' OR '1'='1' --、pass = anything → 以第一個用戶身分登入 (通常為管理員)。

根本原因:資料與代碼未分離

所有範例共同點:**使用者輸入直接拼接至 SQL 字串**,導致資料庫將輸入視為指令而非資料。防御核心原則:**永遠使用參數化查詢 / 預備陳述式**。

各語言/平台參數化最佳實踐

平台正確寫法錯誤寫法
PHP (PDO)$stmt = $pdo->prepare("SELECT * FROM users WHERE uname = ?"); $stmt->execute([$uname]);"SELECT * FROM users WHERE uname = '$uname'"
PHP (mysqli)$stmt = $mysqli->prepare("SELECT * FROM users WHERE uname = ?"); $stmt->bind_param("s", $uname);同左
ASP.NET (ADO.NET)cmd.CommandText = "SELECT * FROM Users WHERE UserName = @u"; cmd.Parameters.AddWithValue("@u", userName);"SELECT * FROM Users WHERE UserName = '" + userName + "'"
Java (JDBC)PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE uname = ?"); ps.setString(1, uname);Statement stmt = conn.createStatement(); "SELECT * FROM users WHERE uname = '" + uname + "'"
SQL Server (T-SQL)EXEC sp_executesql N'SELECT * FROM Users WHERE UserName = @u', N'@u nvarchar(50)', @u = @UserName;EXEC('SELECT * FROM Users WHERE UserName = ''' + @UserName + '''')
Python (DB-API)cur.execute("SELECT * FROM users WHERE uname = %s", (uname,))cur.execute("SELECT * FROM users WHERE uname = '" + uname + "'")

深度防禦:超越參數化

  1. 最小權限資料庫帳號:Web 應用僅擁有 SELECT/INSERT/UPDATE/DELETE 特定表權限,無 DROP/ALTER/xp_cmdshell。
  2. 輸入驗證與白名單:排序欄位 sortby 必須在白名單中 (['UserID','CreateDate','LastLogin']);分頁參數 min/max 強制轉型 int 並檢查範圍。
  3. 錯誤訊息不外洩:生產環境關閉詳細錯誤回傳,統一記錄至日誌,前端顯示友善提示。
  4. WAF / 參數化存儲過程:雲端 WAF (Azure Front Door, AWS WAF) 攔截明顯攻擊模式;核心邏輯封裝於參數化預存程序,應用僅呼叫 EXEC usp_GetUsers @Country。
  5. 定期掃描與滲透測試:CI/CD 管線整合 SAST (SonarQube, Checkmarx) 掃描 SQL 拼接模式;年度第三方滲透測試。
  6. 資料庫審計:啟用 SQL Server Audit / Extended Events 記錄失敗登入、權限變更、大量資料異動、動態 SQL 執行。

常見誤區破解

誤區真相
「我用 stored procedure 就安全」若 SP 內部仍用字串拼接 EXEC('SELECT * FROM T WHERE C = ' + @v),同樣可注入。
「我過濾單引號就夠了」編碼繞過、二次注入、數值型注入 (無需引號)、寬字元注入均可繞過。
「ORM (EF/Hibernate) 自動防注入」ORM 參數化 LINQ/HQL 安全,但 FromSqlRaw/CreateSQLQuery 仍可拼接,需代碼審查。
「內部系統不需防注入」內部威脅、橫向移動、供應鏈攻擊同樣利用注入。零信任原則:所有輸入皆視為不信任。

總結:防禦清單


[ ] 所有 SQL 使用參數化查詢 / 預備陳述式
[ ] 動態排序/分頁/欄位名採白名單驗證
[ ] 資料庫帳號最小權限、移除危險擴展預存程序
[ ] 錯誤訊息不回傳前端、啟用審計日誌
[ ] CI/CD 整合 SAST 掃描 SQL 拼接模式
[ ] 定期滲透測試、WAF 規則更新
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved