基本概念
SQL注入是OWASP Top 10安全風險之一,它利用了應用程序對用戶輸入數據的不當處理。當應用程序直接將用戶輸入拼接到SQL查詢中而沒有進行適當的過濾或轉義時,就可能發生SQL注入攻擊。
攻擊原理
假設有一個登錄表單的SQL查詢:
SELECT * FROM users WHERE username = '[用戶輸入的用戶名]' AND password = '[用戶輸入的密碼]'
如果攻擊者輸入:
用戶名: admin' --
密碼: 任意
實際執行的SQL變為:
SELECT * FROM users WHERE username = 'admin' --' AND password = '任意'
--
是SQL注釋符號,使得密碼檢查被忽略,攻擊者可以無需密碼就以admin身份登錄。
防御措施
現代的web系統基本上很難出現sql注入
1. 可以從前端進行防護,檢驗用戶名是否有非法字符,如'-'?等
2. 即使前端防護過了,后端也不會寫顯式sql,一般會用一些orm框架,就是把數據庫中的表當作類,每一行就是一個類的實例
這樣做有2個好處,一是可以防止sql注入,因為你會發現,在這個例子中本質上是利用了字符串的拼接。二是提供了更上一層的抽象,每個數據庫雖然都是遵循sql標準,但是各個語法都會有些許差別,假如你的系統從mysql遷移到oracle數據庫,那寫顯式sql你就必須更改每一條語句。一個系統中的查詢邏輯可能多達幾千條,難道一條一條改嘛,所以現代的web系統都增加orm框架
3. 就是從數據庫角度進行防護,比如白名單,我定義好有哪些語句可以查詢,sql注入本質上是更改了查詢的邏輯,更改后的不在白名單里,根本不讓你查。
所以現代web系統基本上不會存在sql注入的風險
orm框架
@Entity? ? ? ? ?//這個類是一個?JPA 實體,對應數據庫中的一張表。
@Table(name = "users")? //顯式指定該類映射到數據庫中的表名為?users? ??
public class User {@Id? ? ? ? ? ? //標注?id?字段是表的主鍵private Long id;private String name;
}Query<User> query = session.createQuery(? ??"FROM User WHERE name = :name", User.class
);
query.setParameter("name", inputName); ?
這個是java語法,就是數據庫中有一個user表,表中有兩個字段,id和name,我把這個表抽象成一個類,查詢的時候輸入用戶名,用User.name的私有成員代替,避免字符串直接拼接。
現在每一個后端語言,都有orm框架,甚至在這個框架之上又衍伸出來更高一層的框架,比如java的mybatis等等。