SQL Injection 防護

攻擊範例

# ❌ 危險寫法 - SQL Injection
user_input = "' OR '1'='1"
query = f"SELECT * FROM users WHERE email = '{user_input}'"
# 變成: SELECT * FROM users WHERE email = '' OR '1'='1'
# 回傳所有使用者!!!

# ✅ 安全寫法 - 參數化查詢
import psycopg2
conn = psycopg2.connect("dbname=test")
cur = conn.cursor()
cur.execute("SELECT * FROM users WHERE email = %s", (user_input,))

ORM 防護(Supabase)

// ✅ Supabase 安全查詢
const { data } = await supabase
  .from('users')
  .select('*')
  .eq('email', userInput)  // 自動參數化

Vibe Prompt

「幫我檢查這段程式碼的 SQL Injection 風險,並改成安全的參數化查詢。」

# 請修復這段程式碼
username = request.GET['username']
query = f"SELECT * FROM users WHERE username = '{username}'"

關鍵要點

  • ✅ OWASP Top 10 = Web 應用安全最具權威的風險列表
  • ✅ SQL Injection:永遠使用參數化查詢,不要串接字串
  • ✅ XSS:對使用者輸入進行轉義(Escape),使用 CSP Header
  • ✅ CSRF:使用 SameSite Cookie + CSRF Token 雙重保護
  • ✅ 安全是設計階段就要考慮的,不是上線前才補

OWASP Top 10 (2021)

| 排名 | 漏洞 | 說明 | |:----:|------|------| | A01 | 權限控制失效 | IDOR、越權 | | A02 | 加密機制失效 | 未加密敏感資料 | | A03 | 注入攻擊 | SQL、NoSQL、Command Injection | | A04 | 不安全設計 | 安全未在設計階段考慮 | | A05 | 安全配置錯誤 | 預設密碼、未關閉除錯模式 | | A06 | 脆弱元件 | 使用有已知漏洞的套件版本 | | A07 | 認證與身分管理失效 | 弱密碼、Session 固定 | | A08 | 資料完整性失效 | 不安全的反序列化 | | A09 | 日誌與監控不足 | 無法偵測攻擊 | | A10 | SSRF | 伺服器端請求偽造 |


各語言安全查詢範例

# Python - psycopg2 (PostgreSQL)
cur.execute("SELECT * FROM users WHERE email = %s", (email,))

```javascript
// Node.js - pg
await client.query("SELECT * FROM users WHERE email = $1", [email])

```go
// Go - database/sql
db.Query("SELECT * FROM users WHERE email = $1", email)

```java
// Java - JDBC
PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE email = ?");
ps.setString(1, email);

進階攻擊:Second-Order SQL Injection

即使使用了參數化查詢,如果應用程式從資料庫讀取資料後又將其串接到新查詢中,仍可能觸發攻擊:

1. 使用者註冊時使用者名稱為 "admin'--"
2. 資料庫安全地儲存了這個使用者名稱
3. 管理員在後台執行 "SELECT * FROM users WHERE name = '" + user.name + "'"
4. 觸發注入!

解決方案:不僅在寫入時使用參數化查詢,在讀取後的任何二次查詢也必須使用參數化。

ORM 的安全陷阱

ORM(如 Prisma、TypeORM、Sequelize)預設是安全的,但以下情況可能繞過保護:

// ❌ 不安全:使用原始查詢
prisma.$queryRawUnsafe(`SELECT * FROM users WHERE id = ${id}`)

// ✅ 安全:使用參數化
prisma.$queryRaw`SELECT * FROM users WHERE id = ${id}`


SQL Injection:經典不滅的漏洞

SQL Injection 是 Web 安全中最古老但也最危險的漏洞之一。它是 OWASP Top 10 的常客,每年仍然造成大量資料外洩事件。

為什麼 Parameterized Query 可以防 SQL Injection?

-- ❌ 錯誤:字串拼接
-- 輸入:' OR '1'='1
SELECT * FROM users WHERE email = '' OR '1'='1'
-- 回傳所有使用者!登入成功!

-- ✅ 正確:參數化查詢
-- 輸入:' OR '1'='1
SELECT * FROM users WHERE email = ?
-- 資料庫把整個 ' OR '1'='1 當成字串值
-- 找不到這個 email,登入失敗

參數化查詢(Prepared Statement)把 SQL 語法和使用者輸入分開——輸入永遠被當成資料,不會變成語法的一部分。

下一章預告:XSS 與 CSP

SQL Injection 攻擊的是資料庫。下一章的 XSS 攻擊的是瀏覽器——讓受害者執行惡意 JavaScript。

會員專屬免費教學

本章節為註冊會員專屬的免費開放內容!請先登入或註冊會員,即可立即解鎖閱讀。

立即登入 / 註冊