什麼是 SQL Injection?又該如何預防?
在 Web 開發中,SQL Injection(SQL 注入) 是最常見且危害極大的資安漏洞之一。它可以讓攻擊者透過竄改 SQL 查詢語句來未授權地讀取、修改、甚至刪除資料庫中的資料。本文將帶你認識 SQL Injection 是什麼、實際攻擊範例,以及開發者該如何有效預防這種攻擊。
SQL Injection 是什麼?
SQL Injection 是一種將惡意 SQL 語句插入應用程式輸入欄位中的攻擊方式,目的是操控原本預期的 SQL 查詢邏輯。
舉例來說,假設以下是一段不安全的登入邏輯:
# ❌ 極度危險的程式碼
username = input("請輸入帳號:")
password = input("請輸入密碼:")
query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
cursor.execute(query)
當攻擊者輸入以下資料時:
username
:' OR 1=1 --
password
:任意內容
查詢語句將變成:
SELECT * FROM users WHERE username = '' OR 1=1 --' AND password = '任意內容'
由於 --
是 SQL 的註解符號,後面的內容會被忽略,而 OR 1=1
永遠為真,攻擊者即可繞過密碼驗證成功登入!
SQL Injection 的潛在危害
- 繞過身份驗證:如上例,攻擊者可直接登入任意帳戶。
- 資料洩漏:SELECT 語句被竄改,可讀取整個資料表。
- 資料破壞:透過 INSERT/UPDATE/DELETE 修改或刪除資料。
- 系統控制:某些情況下可執行資料庫指令進而控制伺服器。
如何預防 SQL Injection?
防範 SQL Injection 是開發者的責任,以下是幾種有效的預防方式:
1. 使用參數化查詢(Prepared Statements)
最根本的解法是使用參數化查詢,將使用者輸入與 SQL 語句分離。
以 Python(Django ORM)為例:
# ✅ 安全寫法(ORM 自動處理 SQL 注入風險)
User.objects.filter(username=username, password=password).exists()
以 Python 搭配 psycopg2 原生查詢為例:
# ✅ 安全寫法(使用參數化)
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (username, password))
2. 使用 ORM(Object-Relational Mapping)
ORM 框架(如 Django ORM、SQLAlchemy)天生會處理 SQL Injection 的風險,因為它們自動將參數轉義為安全格式。
3. 輸入驗證與清洗
雖不能取代參數化查詢,但針對表單輸入進行格式驗證(如 email 格式、字數限制)可降低惡意資料混入。
4. 最小權限原則(Least Privilege)
資料庫帳號應只授予應用程式所需的最低權限。避免使用擁有 DROP、GRANT 等高權限的帳號。
5. 使用 Web 應用防火牆(WAF)
WAF 可自動攔截常見的 SQL Injection 攻擊模式,作為第二道防線。
如何檢測是否有 SQL Injection?
- 使用自動化工具(如 sqlmap)對 API 或表單送出測試 payload。
- 開發階段可使用 lint 工具檢查潛在的不安全 SQL 組合。
- 確保有完整的測試覆蓋對外輸入的功能。
面試回答
SQL Injection 是一種資安攻擊手法,攻擊者在表單輸入或 URL 中注入惡意 SQL 語句,藉此操控原本的資料庫查詢邏輯,可能造成未授權的資料讀取、修改,甚至整個資料庫被破壞。
舉例來說,若在登入功能中直接把使用者輸入組合成 SQL 字串而未加防護,攻擊者就能透過像 ' OR 1=1 --
的輸入繞過驗證。
預防方式主要有三個:
- 使用參數化查詢(Prepared Statements):將輸入值與 SQL 語句分離,是最根本的解法。
- 使用 ORM 框架:像是 Django ORM、SQLAlchemy 會自動處理參數轉義。
- 避免直接拼接 SQL,並搭配輸入驗證與資料庫權限控管,從多層面加強安全性。
在我自己的專案中,例如使用 Django 框架時,會透過 ORM 查詢,確保使用者輸入不會直接進入 SQL 字串,並依角色限制資料庫操作權限,確保資安基本面不被忽略。
總結
安全措施 | 是否必要 | 備註 |
---|---|---|
參數化查詢 | ✅ 必須實作 | 最根本防禦方式 |
ORM 框架 | ✅ 強烈建議 | 自動處理轉意 |
輸入驗證 | ⚠️ 輔助防禦 | 不能單獨依賴 |
資料庫權限控制 | ✅ 應落實 | 防止資料被大規模破壞 |
Web 防火牆 | ⚠️ 加強防禦 | 作為額外保護 |
SQL Injection 是老生常談但仍極常見的安全漏洞,唯有落實安全開發習慣,才能避免這類攻擊發生。