
- SQL 教程
- SQL 首頁
- SQL 概述
- SQL - RDBMS 概念
- SQL - 資料庫
- SQL - 語法
- SQL - 資料型別
- SQL - 運算子
- SQL - 表示式
- SQL 資料庫
- SQL - 建立資料庫
- SQL - 刪除資料庫
- SQL - 選擇資料庫
- SQL - 重新命名資料庫
- SQL - 顯示資料庫
- SQL - 資料庫備份
- SQL 表
- SQL - 建立表
- SQL - 顯示錶
- SQL - 重命名錶
- SQL - 截斷表
- SQL - 克隆表
- SQL - 臨時表
- SQL - 修改表
- SQL - 刪除表
- SQL - 刪除表
- SQL - 約束
- SQL 查詢
- SQL - 插入查詢
- SQL - 選擇查詢
- SQL - SELECT INTO
- SQL - INSERT INTO SELECT
- SQL - 更新查詢
- SQL - 刪除查詢
- SQL - 排序結果
- SQL 檢視
- SQL - 建立檢視
- SQL - 更新檢視
- SQL - 刪除檢視
- SQL - 重新命名檢視
- SQL 運算子和子句
- SQL - WHERE 子句
- SQL - TOP 子句
- SQL - DISTINCT 子句
- SQL - ORDER BY 子句
- SQL - GROUP BY 子句
- SQL - HAVING 子句
- SQL - AND & OR
- SQL - 布林 (BIT) 運算子
- SQL - LIKE 運算子
- SQL - IN 運算子
- SQL - ANY, ALL 運算子
- SQL - EXISTS 運算子
- SQL - CASE
- SQL - NOT 運算子
- SQL - 不等於
- SQL - IS NULL
- SQL - IS NOT NULL
- SQL - NOT NULL
- SQL - BETWEEN 運算子
- SQL - UNION 運算子
- SQL - UNION 與 UNION ALL
- SQL - INTERSECT 運算子
- SQL - EXCEPT 運算子
- SQL - 別名
- SQL 連線
- SQL - 使用連線
- SQL - 內連線
- SQL - 左連線
- SQL - 右連線
- SQL - 交叉連線
- SQL - 全連線
- SQL - 自連線
- SQL - 刪除連線
- SQL - 更新連線
- SQL - 左連線與右連線
- SQL - UNION 與 JOIN
- SQL 鍵
- SQL - 唯一鍵
- SQL - 主鍵
- SQL - 外部索引鍵
- SQL - 組合鍵
- SQL - 備選鍵
- SQL 索引
- SQL - 索引
- SQL - 建立索引
- SQL - 刪除索引
- SQL - 顯示索引
- SQL - 唯一索引
- SQL - 聚簇索引
- SQL - 非聚簇索引
- 高階 SQL
- SQL - 萬用字元
- SQL - 註釋
- SQL 注入
- SQL - 託管
- SQL - MIN & MAX
- SQL - NULL 函式
- SQL - CHECK 約束
- SQL - DEFAULT 約束
- SQL - 儲存過程
- SQL - NULL 值
- SQL - 事務
- SQL - 子查詢
- SQL - 處理重複項
- SQL - 使用序列
- SQL - 自動遞增
- SQL - 日期和時間
- SQL - 遊標
- SQL - 公共表表達式
- SQL - GROUP BY 與 ORDER BY
- SQL - IN 與 EXISTS
- SQL - 資料庫調優
- SQL 函式參考
- SQL - 日期函式
- SQL - 字串函式
- SQL - 聚合函式
- SQL - 數值函式
- SQL - 文字和影像函式
- SQL - 統計函式
- SQL - 邏輯函式
- SQL - 遊標函式
- SQL - JSON 函式
- SQL - 轉換函式
- SQL - 資料型別函式
- SQL 有用資源
- SQL - 問答
- SQL - 快速指南
- SQL - 有用函式
- SQL - 有用資源
- SQL - 討論
SQL 注入
如果您透過網頁獲取使用者輸入並將其插入 SQL 資料庫,則您可能存在一個名為SQL 注入的安全漏洞風險。本章將教您如何預防此問題,並幫助您保護伺服器端指令碼(例如 PERL 指令碼)中的指令碼和 SQL 語句的安全。
SQL 注入
SQL 注入是一種安全攻擊,它利用資料庫中的漏洞來執行惡意查詢。這將允許攻擊者訪問敏感資料,篡改資料以及永久刪除資料。
注入通常發生在您向用戶索取輸入(例如他們的姓名)時,他們提供的不是姓名,而是一個您會在不知情的情況下在資料庫上執行的 SQL 語句。永遠不要信任使用者提供的資料,只有在驗證後才能處理此資料;通常,這是透過模式匹配完成的。
示例
在下面的示例中,name 限制為字母數字字元加上下劃線,長度在 8 到 20 個字元之間(您可以根據需要修改這些規則)。
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) { $result = mysqli_query("SELECT * FROM CUSTOMERS WHERE name = $matches[0]"); } else { echo "user name not accepted"; }
為了演示這個問題,請考慮以下摘錄:
// supposed input $name = "Qadir'; DELETE FROM CUSTOMERS;"; mysqli_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");
此函式呼叫應該從 CUSTOMERS 表中檢索一條記錄,其中 name 列與使用者指定的 name 匹配。在正常情況下,$name 只包含字母數字字元和空格。但是在這裡,透過將一個全新的查詢附加到 $name,對資料庫的呼叫變成了災難;注入的 DELETE 查詢刪除了 CUSTOMERS 表中的所有記錄。
幸運的是,如果您使用的是 MySQL,mysqli_query() 函式不允許查詢堆疊或在一個函式呼叫中執行多個 SQL 查詢。如果您嘗試堆疊查詢,則呼叫會失敗。
但是,其他 PHP 資料庫擴充套件(例如SQLite 和PostgreSQL)會愉快地執行堆疊查詢,執行一個字串中提供的所有查詢,並造成嚴重的安全問題。
防止 SQL 注入
您可以在 PERL 和 PHP 等指令碼語言中巧妙地處理所有跳脫字元。PHP 的 MySQL 擴充套件提供了函式mysql_real_escape_string() 來轉義對 MySQL 特殊的輸入字元。
if (get_magic_quotes_gpc()) { $name = stripslashes($name); } $name = mysql_real_escape_string($name); mysqli_query("SELECT * FROM CUSTOMERS WHERE name='{$name}'");
LIKE 難題
為了解決 LIKE 難題,自定義轉義機制必須將使用者提供的 '%' 和 '_' 字元轉換為字面量。使用addcslashes(),這是一個允許您指定要轉義的字元範圍的函式。
$sub = addcslashes(mysql_real_escape_string("%str"), "%_"); // $sub == \%str\_ mysqli_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");