假如你開發了一個網站,有user登入的功能,駭客故意輸入SQL語法來破壞原本的SQL結構,這就是SQL注入攻擊。
以下直接用程式碼來了解:
想像L28, 29是user輸入的帳號密碼,在正常情況下可以成功查出這個user。
正常情況下SQL長這樣:
SELECT * FROM user where account = 'abc' and password = '123'
現在我把程式碼L29改成這樣:
結果還是一樣成功找出這個user了!
因為現在SQL變成這樣了:
SELECT * FROM user where account = 'abc' and password = 'xxx' or '1'='1'
雖然沒有密碼是xxx的,但是'1'='1'是成立的,因此這個table資料就被撈出來了!
一般登入驗證成功後,可能不會把帳密撈出來,但是駭客透過這種方式還是可以登入成功,雖然不知道你的密碼。
這個攻擊的示範還只是把資料抓出來而已,那如果是下delete呢?
防禦SQL Injection:
1. 將user輸入的SQL關鍵字select or ' " 等等字元過濾。
2. 資料庫中儲存加密後的密碼,後端接收到user輸入的密碼後,先進行密碼加密,再組select SQL來驗證是否資料比對成功。
3. 將資料庫不必要的權限拔除,例如把drop table權限拿掉、不需要delete的table就不要grant權限給該db user。
4. 程式使用Prepared statement bind params的方式來下SQL:
將程式碼改成這樣:
可以發現雖然L29被sql injection,但是卻沒撈出結果。
利用L38把最後執行的SQL print出來可以發現,最終執行的SQL是這樣:
SELECT * FROM user where account = 'abc' and password = 'xxx\' or \'1\'=\'1'
因為bindParam幫我們把單引號跳脫掉了,因此避開了SQL Injection攻擊。
5. 使用ORM