報表的 SQL 注入風險是什麼意思?如何防範?

bubblegum發表於2020-07-20

啥是 SQL 注入風險?

資料庫要執行 SQL 訪問資料,資料庫是個執行機構,它只會檢查傳來的 SQL 是不是合乎語法,而並不會關心這個語句是否會造成傷害(資料洩露或破壞)。正因為只要符合語法規則就會執行的機制,導致 SQL 有了注入的風險。
SQL 本身就是個字串,而且一般沒有加密,字串可能被駭客劫持修改,這樣就可能造成資料庫執行了不該執行的動作。
SQL 注入的慣用做法是透過把 SQL 子串插入到 Web 表單項或頁面請求(Url)的查詢字串中提交,最終達到欺騙伺服器執行惡意操作的目的。
常見案例包括透過植入 SQL 騙過登入驗證。而之前很多影視網站洩露 VIP 會員密碼的事件,很多就是透過 SQL 植入到 WEB 表單暴露的,並且這類表單特別容易受到攻擊。透過 SQL 植入,不僅可以非法獲取賬號資訊,嚴重的還能夠篡改、刪除重要資料資訊。

那麼,SQL 注入和報表又有啥關係?

報表的常見資料來源是資料庫,尤其關聯式資料庫,執行 SQL 實現取數。
所有的報表工具都會提供引數功能,主要用於使用者輸入條件後的資料篩選。比如,希望查詢指定時間段的資料,可以把時間段作為引數傳遞給報表,報表在從資料庫中取數時將這些引數拼接到取數 SQL 的 WHERE 條件上,就可以根據不同引數取出不同資料來展現了。這種方式要求事先把查詢條件做死,也就是固定了對應的條件欄位。 比如下面這種傳統做法:
SQL:select * from t where date>=? and date<=?
這個 SQL 專用於按時間段查詢,如果想用地區查詢就搞不了,需要再做一個 area=? 的查詢條件或報表,顯然非常麻煩……

固定條件不夠,還要求更靈活,大多數報表工具又增加了通用查詢功能,允許動態拼 SQL 了。比如,SQL 可以寫成:
select … from T where ${mac}
其中 ${mac} 就是將來會被引數 mac 動態替換的內容。按時間段查詢時,可以把 mac 拼成 date>… and data <=…,按地區查詢時則拼成 area=…;當然還可以混合多條件查詢拼成 data>… and date<=… and area=…;而無條件時則拼成一個永遠為真的條件 1=1。
開了這個口子,報表查詢條件確實靈活了,但是一旦被駭客利用,資料就危險了。

例如上面的 mac 拼入“1=0 union all select … from user”,所有的使用者資訊就可能完全洩露,這也解釋了報表為啥有 SQL 注入風險。

知道了原因,接下來就要考慮報表如何防範 SQL 注入。

總結來說有這麼幾種方式:

第一種:報表不提供靈活查詢的功能

也就是不用動態拼 SQL 方式開發報表,那就沒辦法注入幹壞事兒的 SQL 串了。好處顯然是避免了 SQL 注入的風險,所以像開源報表工具就直接不提供靈活條件功能(犧牲掉產品的功能,如果非要搞靈活條件只能去硬編碼)。對於提供了靈活條件的產品,簡單粗暴地不允許使用這個功能就是了。

第二種:寫牛 X 的 SQL

找資料庫管理牛人,把 SQL 搞成不管引數傳來啥內容,拼到報表的 SQL 裡都能保證正常條件串仍然可執行,攻擊串則非法不可執行。不過這種方式只能說太麻煩、太難(一般人整不了)了,成本忒高(總不能一個報表開發人員還得配個自身 DBA?)。
還是用上面的例子,這個 SQL:select * from T where ${mac},怎麼才能防住所有可能的攻擊呢?
條件上加上括號,寫成
select… from T where (${mac})
的形式。正常的條件串傳進來仍然是合法可執行的,而上面那個攻擊串傳進來之後,SQL 將變成:
select… from T where (1=0 union select … from user)
這是一句不合語法的 SQL,執行會出錯,風險似乎就沒有了。 且慢,如果駭客把 mac 拼成
1=0) union select … from user where (1=1
整句 SQL 將變成
Select … from T where (1=0) union select … from user where (1=1)
還是一句可執行的合法 SQL,仍然會洩露資訊。
原則上,我們要假定最壞情況,要保證駭客即使知道資料庫結構和報表 SQL 寫法時,仍然無法攻擊。我們只能把這個 SQL 寫得更復雜一些:
select … from T where (${mac}) or ${mac}
正常的條件串仍然還是合法可執行的,攻擊串送進來會變成:
select … from T where (1=0) union select … from user where (1=1) OR 1=0) union select … from user where (1=1
這就非法了,可以擋住這個攻擊。
弄成這個樣子才可能擋住所有的 SQL 注入攻擊,但實際上這個 SQL 已經有點複雜了,而且 SQL 寫成這樣,執行效率也會受到影響,條件有時候會被執行兩次(當 w 為假時,第二遍 w 會沒必要地再計算一次)。但為了安全性,卻沒有什麼好辦法。 這個例子說明,想擋住 SQL 注入攻擊並不是非常輕鬆的事情,更不是一般的報表開發人員(相當多對安全意識不夠強)可以做到的。

第三種:對引數值進行敏感詞監測,及時攔截

只需要對引數值(SQL 子串)進行檢測,當包含某些特定詞(或敏感詞)的時候直接拒絕繼續運算報表,比如很少會用 select,from、union 等這些關鍵字作為庫表欄位名,只要判斷條件串中有這些詞,就認為是攻擊並中斷報表執行。

當然了,SQL 的條件串里正常情況下也可能會有這些關鍵字,但是相對較少,為了更好的安全性,這點靈活性的損失還是可以理解的。
這種方式,商業報表開發工具一般都會提供(上圖敏感詞配置為潤乾報表實現方式),也不排除有些報表工具只提供拼 SQL 實現靈活條件的方案,但沒考慮規避 SQL 注入風險,是很危險的。

總結來說,只要報表用到 SQL 的靈活條件查詢功能,就存在注入風險,完全放棄此功能有點一刀切的意思,好的功能還是要發揮其作用的,我們更應該儘可能做好防範。

擴充套件閱讀:


報表的 SQL 植入風險及規避方法

對進一步報表和 BI 技術感興趣的同學還可以搜尋“乾學院”,上面有整套的免費“商業智慧”技術課程,. 或者直接點下面的連結也可以 :


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69957599/viewspace-2705605/,如需轉載,請註明出處,否則將追究法律責任。

相關文章