iT邦幫忙

2021 iThome 鐵人賽

DAY 14
0
Modern Web

工作後才知道的後端 30 件小事系列 第 19

面試題:什麼是 SQL injection?如何預防?

什麼是 SQL injection

透過網頁 input 或 url,在送資料的時候帶 SQL query 去操作資料庫,可以是新增、刪除或其他操作。

如何防止

簡單來說,就是對輸入的 request 做檢查,把 SQL query 過濾掉。
實作上,PHP 可以透過 PDO 來相對容易做到。

PDO—PHP Data Objects—are a database access layer providing a uniform method of access to multiple databases.

使用 PDO 有兩階段:

  1. 準備指令
  2. 執行

Using prepared statements will help protect you from SQL injection.

透過在準備階段使用 placeholder 去過濾 SQL 達到預防 SQL injection 的效果。

# 有 SQL Injection 風險
$query = $DB->prepare("INSERT INTO users (name, email) values ($name, $email)");
  
# unnamed placeholders
$query = $DB->prepare("INSERT INTO users (name, email) values (?, ?)");

# named placeholders
$query = $DB->prepare("INSERT INTO users (name, email) values (:name, :email)");

bind 是綁定參數到 placeholder

ORM

Object-Relational Mapping

將關連式資料庫的資料映射到物件,好讓我們能用物件導向的邏輯去存取資料庫資料;目前大部分框架都有搭配各自的 ORM,Laravel 搭配的是 Eloquent ORM、Django 搭配的是 Django ORM。

而 Eloquent ORM 基本上是建構在 PDO 之上的,所以使用得當的話是預防 SQL Injection 的。

值得注意的是,還是有一些方法是會有漏洞的,例如 whereRaw()。有 raw 的基本上就是不會去做 SQL 的過濾;使用時就要記得用 placeholder,就是寫那個「?」,而非直接把變數接在 SQL 裡。

// Dont Do
$users = User::whereRaw('age > ? and votes = 100', [25])->get();

// Do
$users = User::whereRaw("age > {$_GET['age']} and votes = 100")->get();

Reference


上一篇
如何讓 Laravel Eloquent 支援 composite key
系列文
工作後才知道的後端 30 件小事19

尚未有邦友留言

立即登入留言