對程式設計者而言,在撰寫程式時最在乎的,莫過於功能能否在預計的期限內完成。如果可以,最好讓程式執行得更有效率些。當然,程式碼的品質也必須有一定的水平。接下來,你可以再列出許多程式設計者會考量的因素,但是,有一點可能是很少程式設計者在撰寫程式時會格外留意的,那就是程式碼的安全性。而缺乏安全性的程式碼,會留下安全性的漏洞,使得有心人士可以加以利用,藉以改變程式原先的正常行為,達成其別有用心的企圖,例如取得重要的敏感資料,甚至更進一步的傳播。

大多數人在撰寫程式時,心裡大概不會帶有太多的「邪念」。呃,我的意思是,他們在處理程式的行為時,不會把程式所面對的環境,想得太過於惡意。使用者都是善良的,想當然爾,他們餵給程式的輸入資料也都是規格書裡所規範的。

只不過,有善就有惡,這個世界還是存在那些不懷好意,等著找出你程式弱點,然後等著給你致命一擊的邪惡人士。

網路蠕蟲的誕生
在網際網路未發達前,在發展程式時,安全性並不是十分受到重視的一環。因為,軟體大多在封閉的環境中運行,能實際接觸到軟體並且與它互動的人員,多半就是程式所預期的正規使用者,因此,會刻意入侵程式的機會,其實不會太高。

但是因為網際網路的存在,許多程式間相互以網路連接,程式甚至以網路服務的型態,公開地對外提供服務,在這種情況下,任何不特定的大眾,都有機會透過網路,連接上你的程式,接著進一步和它發生互動。可想而知的,打著歪腦筋的人自然而然就變多了。

在歷史上,第一個透過網路來感染、擴散的程式,就是大名鼎鼎的Morris Worm。這個運作於網際網路前身ARPANET上的蠕蟲,是一名康乃爾大學的學生Robert Tappan Morris利用Unix作業系統上一個叫做Finger的服務,透過它的程式Fingerd(還有另一個特定版本sendmail)所具有的一個安全性漏洞,設計出這個蠕蟲。這個蠕蟲被施放到網際網路上的Unix主機後,除了感染被施放的主機之外,還會利用網路連往其他的主機,並且繼續擴散感染。當時,雖然這個蠕蟲本身無害,並沒有竊取不當資料或進行其他破壞的舉動,但是因為它本身具有某個程式上的臭蟲,所以造成了它會不停地複製自己,使得受感染的主機速度變得愈來愈慢。當時一經施放,便快速的感染了數千臺主機,因為感染的症狀太明顯了(主機運作變得很慢),因此也很快就被發現了。

雖然這個蠕蟲本身除了感染和擴散之外,沒有進行其他的行為,而且本身還有臭蟲導致它一下子就被察覺了,但是,它的問世示範了透過網路入侵、感染程式的手法,成了之後許多針對系統安全性漏洞所做攻擊的示範。

從Morris Worm的例子中,突顯了運行於網路之上的服務,安全性有多麼的重要。只要有一兩個設計缺陷,就可能被有心人士利用,達成各種可能的目的。在許多軟體專案裡,可能只注意程式有沒有及時完成、程式碼的臭蟲數量是不是減到夠少了、程式執行的效率是否足夠,卻不會太留意程式碼是否具備足夠的安全性強度,而這正是有待我們一起努力的課題。

打一場不對稱的戰爭
在程式碼安全性上的攻守兩方,往往站在不對稱的地位,因為攻擊容易、防守難。怎麼說呢?攻擊者只要找到一個弱點就可以發動攻擊,防守者卻得守住每一點,不能顯露出任何弱點。而防守者多半只能針對已知的攻擊型態去做防備,但是,進攻者卻可能找出或發明新的攻擊型態。

再者,程式碼的安全性需要整個團隊一起維護,一個團隊有十個程式設計者,有九個都適當維護了安全性,但有一位發生了疏忽,那麼還是會留下漏洞,當然也為攻擊者留下了可乘之機。

雖然攻擊的手法層出不窮,要針對它們進行防禦,可能也得使用不同的方式。但是有一些基本的安全性觀念是永遠不變的。

為什麼需要強化身分管理?
安全性系統的基礎,是認證及授權(Authentication/Authorization)機制。

認證機制的工作是在確認某個使用者,的確是他所宣稱的使用者。一般我們會設計所謂「登入(login)」的機制來進行對使用者的認證。認證時使用者需要提供憑據,來證明他就是他所宣稱的使用者,常見的方式是一組密碼,當然,也有些認證機制會配合晶片卡或甚至指紋、靜脈等等。

確定宣稱是某使用者的某使用者的確是某使用者之後,便可以依據他被授予所擁有的權限,允許他進行該權限所對應的工作,這就是授權機制的份內工作了。一旦認證和授權這兩個安全性的基石發生了問題,就會使得系統的安全性因此而動搖。

認證是很多系統會出問題的一個環節。就拿以密碼為基礎的認證系統來說吧,因為密碼是認證的憑據,所以,有不軌行為的人,就會想辦法要取得使用者的密碼。取得密碼有很多方式,例如,可以從網路上截取使用者的密碼。當使用者透過網路來使用系統時,登入時所提供的密碼也會透過網路傳輸到系統端,倘若傳輸的過程沒有進行加密而是明文,那麼由於區域網路大多是共同存取的型態,所以,所傳輸的密碼便是在同一個區域網路的人都有能力讀到。

登入密碼是有可能遭竊的
只要在網路上讀到密碼,便可以偽裝成該使用者的身份,進行一些不被授權的動作。因此,對於安全性敏感度較高的系統,在傳輸敏感的資料時,便應該使用加密的方式來傳輸。例如,可以使用SSL/TLS來為傳輸的資料加密。若是網站應用程式,則可考慮使用HTTPS傳輸協定。這邊就是一個很基本的安全性觀念──任何資訊,只要透過網路傳輸,就有被竊聽的可能性。所以,在設計上一定要加以考慮。

要偷走使用者的密碼,還有別的方式,例如,有些惡意的程式,會從使用者操作介面上去竊取。這是怎麼達到的呢?在Windows作業系統上,可以利用一種叫做API hooking的技巧來達到。

所謂的API hooking就是將自己所寫的函式,掛載到某個(或多個)Process所連結的DLL之上,使得這些Process在執行特定DLL中的函式時,以為它執行DLL中原有的函式,但其實執行的是你所撰寫、外表一模一樣的函式。透過這種方式,可以偷天換日,讓原Process以為它執行的,仍舊是原先的DLL中的函式,卻不知道其實已經被換掉。而通常,在換掉的同時,也會串接回原先真正要被呼叫的函式,所以也仍舊可以保有它原始的作用,你卻可以在這中間加工。

那麼,要怎麼利用API hooking的技巧偷走使用者的密碼呢?因為Windows GUI的元件也會利用作業系統提供之DLL中的函式來操作資訊,一旦DLL中的函式被換成有心人士自己提供的函式時,那麼當使用者在操作介面中輸入密碼時,便可以輕易攔截到使用者所輸入的密碼。所以,許多網路ATM的系統,要求使用者輸入密碼時,都會使用動態鍵盤的方式,同時盡量避免使用Windows GUI元件,為的就是要防止密碼被竊取。

攻擊手法繁多,讓我們下回再繼續介紹。

作者簡介


Advertisement

更多 iThome相關內容