基本的網頁安全與防護 - SQL Injection

現在都依賴 Framework 來幫我們阻擋基本的 SQL Injection 防範

但當我自組 Raw Sql 的時候才發現漏洞百出,基礎防禦都沒做足…

於是,查了一些相關知識,做一些筆記

基礎 SQL Injection 防範

✵ 使用 prepared statementsparameterized queries

  • Using PDO
  • Using MySQLi (MySQLi does true prepared statements all the time.)

🔗 How can I prevent SQL injection in PHP?


✵ 別使用易受攻擊的編碼形式進行連線 (only use utf8 / latin1 / ascii / etc)

  • 別使用 utf8, latin1, ascii 以外的編碼
  • 可以在 MySQL 設定中指定 charset
  • 或針對 MySQL 連線指定編碼,使用 set_charset

🔗 http://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string


✵ 跳脫 input 欄位,使用 mysqli_real_escape_string()

  • 根據 charset 來對字串做特殊字元的跳脫 escaped
  • 一定要指定 charset [重要]

🔗 php manual:mysqli_real_escape_string

🔗 GBK字符集下addslashes、mysql_real_escape_string函数的注入漏洞及解决办法


觀念

SQL Injection 防範是要 跳脫 而非 過濾,不能採用 strip_tags [x]

如果自組 raw sql 一定要:
  • 自行跳脫 (mysqli_real_escape_string())
  • 型態轉換 (int => (int), string => (string))
  • 如果要支援 LIKE
    • 建議要手動跳脫 _(underline), %(percent), \(backslash) 符號,避免被 Injection
    • 使用 addcslashes()_, %, \ 也視為需要跳脫的字元

額外參考