SQL資料隱碼攻擊與防堵方法

作者:李忠憲

一、前言

資料隱碼攻擊約在一年多以前就被發現,當時筆者在系管師研習班的 ASP 課程裡,曾經對參與研習的學員提出說明,隨著時間推移,這個漏洞已經被進一步運用並發展成較為複雜的攻擊程序,也因此其危險性也與日俱增,身為系管師的我們實在不能大意。寫這篇文章的用意是想幫助系管師好好檢查自己的主機是否有被攻擊的可能性,並儘速採取因應對策,以免災害發生時無挽回的餘地。

二、資料隱碼攻擊的成因

ANSI SQL 語法裡,單引號被定義為字串的標示符號,例如底下的語法中,ABC 123 被視為字串

select * from mydatabase where id='ABC' and passwd='123'

一般在 WEB 應用程式裡,ABC 123 這些字串經常是透過表單或查詢字串來輸入,這時候就可能被駭客利用為敲開牆壁的第一塊磚頭,例如在瀏覽器網址列輸入:

login.asp?id=ABC&passwd='%20or%201=1%20or%201='

其中 %20 經過 WEB Server 解譯為空格,而參數帶入 SQL 語法中,變成下面這個恆為真的式子:

select * from mydatabase where id='ABC' and passwd='' or 1=1 or 1=''

這會使得原本讀資料庫判別使用者的程式,被執行結果欺騙而誤以為驗證成功。

這個弱點根源於寫程式的人,沒有將安全防範措施做好,然而利用這個弱點,加上系統上的其他的漏洞,可以發展出一些更為致命的攻擊,例如在瀏覽器網址列輸入:

login.asp?id=ABC&passwd='%20and%20drop%20database%20(select%20XXX%20from%20master.sysdatabases)

參數帶入 SQL 語法中,將會變成:

select * from mydatabase where id='ABC' and passwd='' or drop database (select XXX from master.sysdatabases)

這道命令一旦執行會將除了系統資料庫以外所有的資料庫移除,當然要能如願這樣做還必須有其他條件的配合,例如:存取 mydatabase 的使用者必須擁有 master 資料庫的讀取權限......等等,而根據伺服器的預設值,這些條件經常都能獲得滿足。

運用這個方法,除了可以直接攻擊資料庫外,也可以間接攻擊作業系統的弱點,例如底下這個語法:

select * from mydatabase where id='ABC' and passwd='' or execute master.XXX.xp_cmdshell 'net user test test123 /ADD'

這道命令會要求 SQL 伺服器執行作業系統 net user 指令,在系統上建立駭客入侵用的帳號,而配合其他指令,駭客可以為此帳號配置一些必須的權限。要讓這件事成為可行,首先必須以長字串造成 SQL 伺服器緩衝區溢位而取得 administrator 權限,一旦如此,伺服器甚至整個網路系統就會被駭客予取予求了。

使用非 Windows 平台的 SQL 伺服器也無法倖免於難,因為在 SQL 伺服器的設計上,除了從 WEB 去執行外,也可以透過 NFSRPC 等其他機制來設計應用程式,因此 SQL 伺服器是允許呼叫系統程式來執行的,Windows 是如此,Linux 也是如此。因此將諸如 rm -rf 等系統命令內嵌於 SQL 語法中來執行的情形也就可以被利用作為駭客破壞系統的手段,例如:

spool test.sh select 'rm -rf ' || XXX from sys.dba_data_files /

三、伺服器 PATCH

針對 SQL 資料隱碼攻擊,微軟公司已經數度推出 SQL PATCH ,最新的 PATCH 必須先安裝 SQL2k sp2,然後下載編號 Q316333 PATCH 檔,SQL 7.0 的用戶則須下載 Q318268 PATCH 檔,同時這些修正也將會包含在 SQL sp3  裡面。

特別要注意的是,這些修正只是解決了長字串導致緩衝區溢位的問題,使得 Administrator 的權限更難以取得,然而運用資料隱碼攻擊,駭客仍然得以 Domain User 的權限恣意使用作業系統資源。因此並非 PATCH 過後就沒有問題了。

如前所述由於 SQL 伺服器設計的目的無法將 command shell 的呼叫完全屏除,也無法在權限上給予更多的限制,因此要應付變化繁多的 SQL 資料隱碼攻擊,在 SQL 伺服器上下工夫作用並不大,還是需要程式設計師自己多做些 check 的動作。

四、程式安全檢查

以程式設計的觀點來看,將表單或查詢字串直接帶入 SQL 語法,是一切弊病的源頭,要徹底排除 SQL 資料隱碼攻擊,必須從根源對症下藥。也就是必須在取得表單資料後,針對單引號進行過濾,然後再組合為 SQL 語法例如:

sql_cmd = "select * from mydatabase where id='" & Request("id") & "' and passwd='" & Request("passwd") & "'"

應該改為

myid = Replace(Request("id"),"'","'+chr(34)+'")

mypwd = Replace(Request("passwd"),"'","'+chr(34)+'")

sql_cmd = "select * from mydatabase where id='" & myid & "' and passwd='" & mypwd & "'"

經過如此修改後,原本會造成危害的 SQL 隱碼,就會被套入單引號中,被 SQL 伺服器當成普通字串來處理,而不會去執行它,這樣就可以避免受到資料隱碼攻擊。

select * from mydatabase where id='ABC' and passwd='' or execute master.XXX.xp_cmdshell 'net user test test123 /ADD'

變成

select * from mydatabase where id='ABC' and passwd=''+chr(34)+' or execute master.XXX.xp_cmdshell '+chr(34)+'net user test test123 /ADD'+chr(34)+''

使用 PHP 或其他語言的程式,也必須比照上述方式修改,預估需要修改的程式不在少數,系管師應該盡速進行補修。

而需修改的程式,包括處理表單傳回值的程式以及接受查詢字串的程式,特別是後者經常被程式設計師忽略,然而使用查詢字串來傳回參數的程式,由於可以在網址列直接進行操弄,所以通常是駭客的最愛,這絕對是大意不得的。

如果您曾經從石牌國小下載 web 校務行政系統或者班級經營套件,則除了帳號認證程式已經加以防範以外,其餘程式仍然需要自行手動修改。也就是說,只要是擁有帳號的合法使用者,在通過驗證後就能接觸到其他尚未經過安全修改的程式,從而有機會使用資料隱碼攻擊自己校內的主機,目前估計這樣的危險性應該是不高,無論如何在下一個版本裡,將會徹底解決這個問題。

五、後記

基於安全理由,原本要附上的幾張螢幕抓圖,因為擔心駭客會從中獲得進一步的攻擊靈感,因此決定不附了,文中所提及的攻擊手法也隱去一些內容,然而有經驗的人依然得以拼出全貌,為了要讓眾多的程式設計師了解問題的成因與防堵的方法,冒這點風險畢竟是不可避免的,文中如果有不清楚的地方請當面與我討論,筆者不準備針對前述內容回覆 email 或電話諮詢,敬請見諒!