假如你開發了一個網站,有user登入的功能,駭客故意輸入SQL語法來破壞原本的SQL結構,這就是SQL注入攻擊。
以下直接用程式碼來了解:


正常情況下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
本筆記參考:
1. https://www.itread01.com/content/1549607942.html
2. https://medium.com/%E7%A8%8B%E5%BC%8F%E7%8C%BF%E5%90%83%E9%A6%99%E8%95%89/%E6%B7%BA%E8%AB%87%E9%A7%AD%E5%AE%A2%E6%94%BB%E6%93%8A-%E7%B6%B2%E7%AB%99%E5%AE%89%E5%85%A8-%E4%B8%80%E6%AC%A1%E7%9C%8B%E6%87%82-sql-injection-%E7%9A%84%E6%94%BB%E6%93%8A%E5%8E%9F%E7%90%86-b1994fd2392a