在全部漏洞類型中,SQL 注入但是說是危害最大最受你們關注的漏洞。簡單說來,SQL 注入是經過在用戶可控參數中注入SQL語法,破壞原有SQL結構,達到編寫程序時意料以外結果的攻擊行爲。php
以 ThinkJS 爲例,假設咱們寫了以下一個接口(實際狀況確定不會這麼寫的):html
// user.js module.exports = class extends think.Controller { async loginAction() { const { username, password } = this.post(); const user = await this.model().query( `SELECT * FROM user WHERE name = "${username}" AND password= "${password}"` ); if (think.isEmpty(user)) { return this.fail(); } return this.success(user); } }
當用戶提交的 username
是 admin"; --
的話,最終執行的 SQL 語句就會變成mysql
SELECT * FROM user WHERE name = "admin"; --" AND password= "111"
最終攻擊者就能夠成功登陸 admin 帳號了,這就是最簡單的 SQL 注入了。從上面這個簡單示例中,咱們發現漏洞成因能夠歸結爲如下兩個緣由疊加形成的:git
SQL注入根據攻擊者獲取數據的方式分爲回顯注入、報錯注入以及盲注。github
剛纔演示的直接從返回結果中獲取數據則爲回顯注入,固然也能夠經過 MySQL 執行的報錯結果中嗅探到數據庫的結構和內容,這就是報錯注入。盲注則是根據數據庫執行的延時等操做來判斷是否接近正確值,簡單的說來有點像是拿着聽診器試探保險箱的密碼的感受。web
不一樣的分類原則會有不一樣的分類,也有按照注入位置及方式不一樣進行分類分爲POST注入、GET注入、cookie注入、盲注、延時注入、搜索注入、base64注入等。sql
不過你們都支持分類形式不一樣,原理仍是一致的,這裏就不一一細說了。shell
若是網站存在 SQL 注入漏洞,至關於將數據庫直接暴露在攻擊者面前,可想而知危害會有多大了。攻擊者利用 SQL 注入漏洞能實現如下攻擊:數據庫
從文章開頭能夠看到,其實漏洞的主要緣由仍是沒有對用戶輸入的數據進行過濾,因此對來自用戶的數據(GET, POST, cookie 等)最好作到如下兩種過濾校驗:數組
NaN
致使攻擊失敗。在 ThinkJS 中咱們提供了強大的 Logic 功能能夠方便的對數據進行格式校驗。檢查輸入數據格式在 ThinkJS 中還能防止另一種非通用 SQL 安全問題。文章開頭的示例代碼咱們在實際的應用中通常會這麼寫:
// user.js module.exports = class extends think.Controller { async loginAction() { const { username, password } = this.post(); const user = await this.model('user').where({ name: username, password }).find(); if (think.isEmpty(user)) { return this.fail(); } return this.success(user); } }
當咱們構造如 name=admin&password[]=!%3D&password[]=
的請求參數時,最終執行的 Model 語句就會變成
this.model('user').where({name: 'admin', password: ['!=', '']});
嚴格限制Web應用的數據庫的操做權限,給此用戶提供僅僅可以知足其工做的最低權限,從而最大限度的減小注入攻擊對數據庫的危害。
**請記住永遠不要使用超級用戶或全部者賬號去鏈接數據庫!**
當數據庫被攻擊時將損傷限制在當前表的範圍是比較明智的選擇。經過權限限制能夠防止攻擊者獲取數據庫其它信息,甚至利用數據庫執行 Shell 命令等操做。
當數據庫操做失敗的時候,儘可能不要將原始錯誤日誌返回,好比類型錯誤、字段不匹配等,把代碼裏的 SQL 語句暴露出來,以防止攻擊者利用這些錯誤信息進行 SQL 注入。
除此以外,在容許的狀況下,使用代碼或數據庫系統保存查詢日誌也是一個好辦法。
顯然,日誌並不能防止任何攻擊,但按期審計數據庫執行日誌能夠跟蹤是否存在應用程序正常邏輯以外的 SQL 語句執行。日誌自己沒用,要查閱其中包含的信息才行。畢竟,更多的信息總比沒有要好。
其實在 ThinkJS 中已經將關鍵字處理類的方法已經集成,使用程序提供的 ORM 方法進行 SQL 構造會比本身寫 SQL 語句拼接來的更方便,同時也能提升項目代碼複用,減小潛在的風險。
若是對 ThinkJS 默認的 think-model 不喜歡的話,也可使用其它第三方的 ORM 框架,例如 think-sequelize。