在前一回中,我們介紹了在程式碼安全性上一個最大的威脅,也就是緩衝區溢位的攻擊。這種攻擊的模式,對於網路應用程式來說,尤其能造成可怕的傷害。

所幸,近年來緩衝區溢位攻擊的手法已獲得普遍的重視,除了新型的程式語言針對此做了加強之外,諸如C/C++等程式語言也利用字串程式庫的改進來強化安全性。接下來,便是程式設計者的自我意識要提高警備,針對緩衝區溢位攻擊處處加以防範。

除了緩衝區攻擊之外,這幾年來流行的另一個攻擊,同樣也是可以從不特定的大眾來發動的。因為,一些針對大眾提供服務的系統或是網站,都可能具備這樣的安全性缺陷,使得有心人士可以加以利用,並且進一步進行攻擊。它就是所謂的資料隱碼(SQL Injection)攻擊。

為什麼會有SQL Injection?
SQL(Structured Query Language)是關聯式資料庫系統用來做為查詢及操作資料庫的一種語言。在現今,絕大多數的網站或商業系統,都會利用關聯式資料庫來儲存它們的資料,當然,程式也都會透過SQL來對資料進行操作。

而所謂的SQL注入,便是當網站或系統允許使用者進行一些資料輸入的動作時,將不懷好意的部份SQL述句內容,當做是資料來提供,而因為網站或系統可能將使用者所輸入的資料,拿去組成最後要在資料庫上執行的SQL述句,最後就會得到一個不在程式設計者預料中、而是有心人士刻意製造出來的SQL述句。因為是在資料中暗藏程式碼,所以才會被稱為是「資料隱碼」攻擊。

一個最簡單、但是又能說明資料隱碼攻擊的例子,就是維基百科上關於「SQL資料隱碼攻擊」這個條目的說明範例了:

例如:某個網站的登入驗證SQL查詢代碼為:

strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"

這是多年前很常見到、用來認證使用者輸入的名稱和密碼是否正確。資料庫中可能用一個叫做users的表格,裡頭有一個叫name的欄位用來儲存使用者的名稱,另外還有個pw的欄位,用來記錄使用者的密碼。最常見到的寫法,就是讓使用者在瀏覽器的表格中分別輸入名稱和密碼,一旦使用者送出該表格後,程式碼就原封不動,把名稱和密碼拿去組成上例中strSQL。當在資料庫執行這段SQL能取得資料時,便代表使用者所輸入的名稱及密碼,是和資料庫中所記載的內容相匹配,也就是正確,此時便可以允許使用者登入。

唔,看起來很正常嘛,有什麼不對勁嗎?或許程式設計者從來沒有想過,使用者會試著在這兩個欄位中輸入SQL述句的部份內容,例如輸入:

userName = "' OR '1'='1";
passWord = "' OR '1'='1";


這麼一來,所得到的strSQL就會變成:

strSQL = "SELECT * FROM users WHERE (name = '' OR '1'='1') and (pw = '' OR '1'='1');"

WHERE字句後的內容永遠為真,所以這位使用者就可以登入系統成功了──即使他完全不知道這個系統上有什麼使用者帳號、其密碼又分別是什麼。

有些攻擊甚至不這麼麻煩,直接利用SQL述句提供的註解符號(--),直接忽略掉之後的述句內容。像是:

strSQL = "SELECT * FROM users WHERE (name = 'Admin' --) and (pw = '');"

倘若你的系統中恰好有一個叫Admin的使用者帳號名稱,而通常這種帳號名稱(或像是root、administrator之類的)都意謂著它是超級使用者或系統管理者,那麼不懷好意的人,透過上述的方式,便可以以系統管理者的身分進入,通常也就具備了所有的權限:他可以建立使用者、查看其他使用者密碼等等。想想看,這究竟有多麼的可怕。

除了略入一些檢查條件之外,有心人士可以做的事還更多。有一些資料庫系統允許你輸入批次性的SQL,例如:

select * from table1 select * from table2

便能對兩個表格進行查詢。一旦他試著在你的SQL述句中,注入一些像是:

XXXX‘ drop table TTTT –

之類的內容,那麼,你的TTTT表格就會被刪去。若TTTT恰好是一個系統運作不可或缺的表格時,系統自然會因此而損毀、無法再運作下去。

有心人士會利用SQL述句的疏於檢查,而為所欲為
能夠在打算弄些手腳的機器上想辦法執行一些SQL述句,對有心人士來說,是一件很棒的事情。透過執行一些SQL述句,有心人士有機會進行許多動作。例如他可以得到資料庫中的一些重要資料,例如帳號、密碼、姓名、地址、交易資料等等。如果他是詐騙集團,取得這些個人資料後,便可以用來做為詐騙時取得對方信任的基礎。

他也可以取得資料庫的schema,而schema是系統運作的重要資訊,有了這些,他便更清楚資料庫的表格名稱、欄位名稱。透過這些資訊,便可以推測系統資料的操作方式,以這為基礎,自然可以發動更進一步的攻擊。

當然,他也可以修改其中的資料,例如修改特定使用者甚至系統管理員的密碼,來達成特定的目的。而刪去重要的資料或甚至表格,也能夠造成系統無法正常運作,形同癱瘓系統。
有些資料庫系統,甚至提供了一些作業系統的支援,允許從SQL述句中執行命令列指令。這更可怕了,這等於是允許有心人士自由自在地透過注入SQL的述句內容,在資料庫主機上執行各種命令列指令。

所以簡單來說,資料隱碼攻擊,就是在原本該出現資料的地方,置入SQL述句碼、甚至是其他類型的程式碼,來造成攻擊。

你可能會問,除了SQL述句碼之外,還能夠塞什麼樣的程式碼進去來造成攻擊呀?有一些網站,會將使用者所輸入的資料內容做為網頁HTML輸出時的部份內容,例如,一個論壇網站,便可能將使用者所寫下的發言內容記錄在資料庫中,而到了要呈現發言內容時,再從資料庫中讀出,成為要輸出至讀者瀏覽器HTML網頁的部份內容。

這樣的設計方式,乍看之下很合理,但是,如果留言的內容是一段HTML碼,然後暗藏著執行JavaScript呢?那麼在觀看者的瀏覽器上,就有可能執行到一段不懷好意的JavaScript程式碼了。

要驗證處理使用者發出的任何資料
程式原本以為該接收到的是使用者輸入的資料,收到的卻是程式碼或SQL述句碼,這其實是緩衝區溢位攻擊和資料隱碼攻擊的共通特性。

它們都透過將要執行的程式碼動作暗藏在資料之中,並且觸發執行這些動作來造成攻擊。這說明了,想要寫出安全的程式碼,最基本、最重要的心態便是千萬不要相信來自於使用者的任何資料。你必須假設資料都有可能是惡意的、不是如你所想像的,你才能處處做好防備。如何因應資料隱碼攻擊,讓我們下回再見分曉。

作者簡介


Advertisement

更多 iThome相關內容