Back to Blog

SQL Injection 攻擊的原理與防範

#什麼是 SQL Injection?

SQL Injection (SQL 注入) 是一種常見的網站安全漏洞,攻擊者可以利用這個漏洞,將惡意的 SQL 查詢語法注入到您的網站中,從而讀取、修改、刪除您的資料庫中的資料。

#SQL Injection 的攻擊原理

SQL Injection 的攻擊原理是,當您的網站在處理使用者輸入的資料時,沒有對使用者的輸入進行充分的過濾和檢查,就直接將使用者的輸入拼接到 SQL 查詢語法中,從而讓攻擊者可以控制 SQL 查詢的語意。

範例:

假設您有一個登入表單,您的 SQL 查詢語法如下:

SELECT * FROM users WHERE username = '$username' AND password = '$password'

如果使用者在密碼欄位中輸入 ' OR 1=1 --,那麼您的 SQL 查詢語法就會變成:

SELECT * FROM users WHERE username = 'admin' AND password = '' OR 1=1 --'

因為 OR 1=1 永遠為 true,所以這個查詢會回傳 users 表中的所有資料,攻擊者就可以成功登入。

#SQL Injection 的攻擊類型

  • In-band SQLi: 攻擊者可以直接在同一個通訊頻道中看到攻擊的結果。
  • Blind SQLi: 攻擊者無法直接看到攻擊的結果,但可以透過觀察伺服器的回應來判斷攻擊是否成功。
  • Out-of-band SQLi: 攻擊者可以透過其他的通訊頻道 (例如 DNS 或 HTTP) 來取得攻擊的結果。

#SQL Injection 的防範方法

防範 SQL Injection 的最好方法是使用預備語句 (Prepared Statements)

預備語句是將 SQL 查詢語法和使用者輸入的資料分開處理。首先,您會先將 SQL 查詢語法的模板送到資料庫伺服器,然後再將使用者輸入的資料作為參數傳送過去。這樣一來,資料庫伺服器就不會將使用者輸入的資料當作 SQL 查詢語法的一部分來解析,從而可以有效地防止 SQL Injection 攻擊。

PHP (PDO) 範例:

<?php

$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');

$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username');
$stmt->execute(['username' => $_POST['username']]);

foreach ($stmt as $row) {
    // ...
}

?>