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

原文地址:http://c.raqsoft.com.cn/article/1591686285242?r=CGQ

 

 

 


啥是 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 植入風險
報表的 SQL 植入風險及規避方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章