我們介紹了緩衝區溢位攻擊、資料隱碼攻擊,以及跨站指令碼攻擊等三種著名的安全性攻擊,在未來,肯定也會有更為新穎的攻擊技巧被發展出來。我們不能僅針對特定、已知的攻擊方式進行防禦,而是應該回歸到設計系統及撰寫程式碼時的共通安全性原則,才有可能更全面地防範。

資料曝露的危機
首先, 你必須評估出正確的資料曝露風險。所指的是什麼呢?你的系統會有儲存、暫存資料的場所及方式,也會有傳輸資料的媒介及方法。而在設計之際,便必須要評估到上述方法,究竟存在多少風險,而你所做的設計,是否能夠在此風險下保持安全無慮。

許多問題,便是因為設計者低估可能存在的風險。例如,某個協助使用者進行網路拍賣商品的工具軟體,直接將使用者的信用卡號碼及認證碼記錄在使用者本機端的檔案中,而且沒有予以加密。

設計者的思維可能是,因為這是執行在使用者自己的電腦,所以即使資料沒有經過加密來保護,其他人也沒有機會可以接觸到這個檔案,而這正是低估了資料曝露的風險。一來,其他人或許真有機會使用到同一部電腦,二來,有心者可能會透過其他途徑而有能力存取到該使用者電腦上的檔案,當設計者低估資料曝露的風險時,所做出來的設計其安全性強度便會不足。

事實上,一個不小心,資料很容易曝露在有心人士的面前。所以,在規畫資料儲存的場所,以及資料儲存的方式時,都必須以謹慎的態度面對。尤其是具敏感性的資料,像是使用者的帳號、密碼、事關商務交易的資訊、等等,都應該提供足夠強度的保護。在資料的保護上,可以使用廣為人知、安全性夠強的加密演算法來處理。

除了資料的儲存必須小心曝露的風險之外,資料傳輸的安全性也是很容易被忽略。原因當然是許多設計者沒有考慮到:網路本身就是一個十分不安全的傳輸媒介,任何透過網路傳輸的資料.都必須假設會被其他人讀走。一些直接將使用者認證資訊未經處理就直接由網路傳輸的設計,便是明顯地低估資料曝露的風險,自然容易成為安全性的問題。

不要過於相信來自於使用者的資料
接著,你必須假設系統之外都是不安全的。在設計你的系統時,在面對任何和你自有系統互動的個體時,都必須假設它們可能是惡意的、甚至是有心人士偽裝成正常使用者或正常外部系統的。在這個原則之下所衍生出來的一個概念就是「所有使用者的輸入資料,都是邪惡的!」

不論是緩衝區溢位攻擊、資料隱碼攻擊、或是跨站指令碼攻擊,全部都是利用系統在接收外部資料時處理上的漏洞來發動攻擊的。而之所以存在這樣的漏洞,便是因為過於相信來自於使用者的資料,才會讓有心人士有機可乘。光是處理來自於使用者的輸入資料時的不留意,就能夠造成這麼大的災難,更別提你的系統除了和使用者互動之外,還有可能和其他的系統接觸。

在設計時,必須假設和這些使用者、外部系統互動的過程以及內容,都有可能是在合理的預期之外,甚至有可能遭受到惡意的侵犯,如此一來,才能適度的做好防備。

不要讓程式執行濫權
接著,要盡量使你的程式碼在最小的權限下運作。不少人都有類似的習慣,在Unix上使用root權限、在Windows上使用系統管理員的身分來執行程式。因為如此一來,程式擁有所有的權限,也就不需要更細緻的進行各種和權限有關的設定。但是,這種偷懶的方式,正是許多災難背後的原因之一。

在古早時候,sendmail的緩衝區溢位攻擊屢屢修正、但也持續遭受攻擊,為什麼它會成為許多攻擊者的目標呢?其中有一個原因是因為要執行sendmail必須要有root權限。

你可以想像,正因為它在執行時會有root權限,一旦緩衝區溢位攻擊發動成功,能夠趁機植入程式碼,那麼所植入的程式碼便能夠以root權限來執行,進而想做什麼就能做什麼,例如幫你更換一個特製版本的telnet daemon之類的,而這便是高權限執行的危險所在──具備愈高權限的程式碼,一旦被攻擊,所造成的傷害就愈大。

因此,在權限設定上,應該要盡可能降低所使用的權限、減少被授權的範圍。正如前文在資料隱碼攻擊中所提到資料庫安全的討論中,倘若避免使用諸如sa之類的系統管理員帳號來連接資料庫,那麼,倘若不幸遭到攻擊而淪陷,也能縮小被攻擊的範圍及程度。

同樣地,在設計及程式碼的撰寫上,也應該盡可能降低程式碼執行時所需的權限,以及授權的範圍。這麼一來,可以降低被攻擊後造成的傷害,甚至避免被攻擊,因為攻擊後能進行的破壞有限。

程式碼要與資料存取的作業方式保持距離
觀察之前介紹的資料隱碼攻擊及跨站指令碼攻擊,之所以會衍生出這些攻擊手法,是因為程式的設計存在一個共通特性──混用了程式碼及資料。
之所以會有漏洞,是因為將使用者所提供的資料,做為欲執行之程式碼的一部份。在資料隱碼攻擊中,讓使用者輸入的資料成為SQL述句的一部份,所以出了問題。而在跨站指令碼攻擊中,則是讓使用者輸入的資料成為HTML碼的一部份。這種安全性漏洞形成開放讓使用者自訂執行的程式碼,讓有心人士把你的系統當做是他執行客製化程式的平臺,自然會構成極大的危機。

正本清源之道,便是不要混用程式碼及資料,讓資料歸資料、程式碼歸程式碼。而不是直接讓資料成為欲執行之程式碼的一部份。倘若資料必須成為程式碼的一部份,那麼程式碼中所運用的資料,必須嚴格確認:它的確是所預期之資料格式,沒有存在成為程式碼的可能性。

越早投入越容易處理,事後再檢核較困難
要撰寫具安全性的程式碼是一件困難的工作,對於程式設計者而言,除了要及時的完成功能、盡量減少臭蟲之外,還得顧及有心人士以那種超乎想像的方式來攻擊程式碼,可以說是相當辛苦,但這同時也是一件具有挑戰性的工作。

想要撰寫具安全性的程式碼,最好在著手開始撰寫之初便將安全性建立,而不能存著日後再來加強,先把功能完成就好的心態。程式碼的安全性,最適當的建立時機,便是在著手設計以及撰寫程式碼的同時。你必須一開始就將安全性考慮在內,並且一次到定位,因為安全性的加強及修補,等到之後再來進行,難度就變高許多了。

雖說目前有不少靜態的程式碼安全性檢測工具,可以輔助我們檢測程式碼的安全,而它們也都能起作用,但是,從程式設計者的觀點來看,根本之道還是應該要了解撰寫安全程式碼的法則及實踐,在一開始就寫出夠安全的程式碼,而不是事後利用工具來找出有問題的部份。畢竟工具並非十全十美,真正的程式碼安全性,還是源自於有安全性觀念的程式設計者。

作者簡介


Advertisement

更多 iThome相關內容