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