防范緩沖區(qū)溢出攻擊,常見的有四種基本方法:強制要求編寫正確的代碼、非執(zhí)行的緩沖區(qū)、數(shù)組邊界檢查和程序指針完整性檢查。
1.編寫正確的代碼
要求編寫正確的代碼是一件非常有意義但耗時的工作,例如C語言編程就非常容易出錯。盡管經(jīng)過長期努力人們知道了如何編寫安全的代碼,具有安全漏洞的程序依然不斷出現(xiàn)。人們開發(fā)了一些工具和技術(shù)來幫助經(jīng)驗不足的程序員編寫安全正確的程序,防范因為緩沖區(qū)溢出漏洞引起的攻擊。這些工具的目的在于通過人為隨機地產(chǎn)生—些緩沖區(qū)溢出來尋找代碼的安全漏洞。還有一些靜態(tài)分析工具用于偵測緩沖區(qū)溢出的存在。雖然這些工具可以幫助程序員開發(fā)更安全的程序,但是由于C語言的特點,它們不可能找出所有的緩沖區(qū)溢出漏洞。偵錯技術(shù)僅能用來減少緩沖區(qū)溢出的可能,并不能完全地消除它的存在。
2.非執(zhí)行的緩沖區(qū)
通過操作系統(tǒng)控制,使得緩沖區(qū)不可執(zhí)行,稱為非執(zhí)行的緩沖區(qū)技術(shù),這是另一種阻止攻擊者植入攻擊代碼的方法。例如可以設(shè)定堆棧數(shù)據(jù)段不可執(zhí)行,這樣就可以最大限度地保證了程序的兼容性。Linux和Solaris系統(tǒng)都發(fā)布了有關(guān)這方面的內(nèi)核補丁。因為幾乎沒有任何合法的程序會在堆棧中存放代碼,這種做法幾乎不產(chǎn)生任何兼容性問題。通過使被攻擊程序的數(shù)據(jù)段地址空間不可執(zhí)行,使得攻擊者不可能執(zhí)行植入到被攻擊程序輸入緩沖區(qū)的代碼,可以阻止很多緩沖區(qū)溢出攻擊的發(fā)生。但是這種方法仍然存在局限性,原因在于UNIX和Windows系統(tǒng)為了實現(xiàn)更好的性能和功能,往往允許在數(shù)據(jù)段中動態(tài)地放入可執(zhí)行的代碼,為了保持程序的兼容性,不可能阻止所有程序的數(shù)據(jù)段都不可執(zhí)行;另外,攻擊者也并不一定都要依靠植入攻擊代碼實現(xiàn)緩沖區(qū)溢出攻擊。
3.數(shù)組邊界檢查
通過利用編譯器進(jìn)行數(shù)組邊界檢查的方法,使得緩沖區(qū)溢出不可能出現(xiàn),從而完全消除緩沖區(qū)溢出的威脅,實現(xiàn)緩沖區(qū)的保護(hù)。攻擊者植入代碼引起緩沖區(qū)溢出是一種手段,擾亂程序的執(zhí)行流程是另一種手段。與非執(zhí)行的緩沖區(qū)保護(hù)策略不同,數(shù)組邊界檢查策略的關(guān)鍵在于只要保證數(shù)組不能被溢出,溢出攻擊也就無從談起。為了實現(xiàn)數(shù)組邊界檢查,則要確保所有對數(shù)組的讀寫操作都應(yīng)當(dāng)被檢查,以保證對數(shù)組的操作在正確范圍內(nèi)進(jìn)行。最直接的方法是檢查所有的數(shù)組操作,通常可采用一些優(yōu)化技術(shù)減少檢查的次數(shù)。
4.程序指針完整性檢查
通過對程序指針進(jìn)行完整性檢查,也可以阻止多數(shù)緩沖區(qū)溢出攻擊。這種方法試圖在程序指針被引用之前檢測到它的改變。因此即便一個攻擊者成功地改變了程序的指針,由于系統(tǒng)事先檢測到了指針的改變,這個指針將不會被使用。與數(shù)組邊界檢查相比,這種方法雖然不能解決所有的緩沖區(qū)溢出問題,但是它在性能上有很大優(yōu)勢,兼容性也很好。
由于最普通的緩沖區(qū)溢出攻擊手段是在堆棧中植入代碼,采用非執(zhí)行的緩沖區(qū)策略,如非執(zhí)行堆棧和堆棧保護(hù)的方法就可以有效防衛(wèi)這種攻擊。非執(zhí)行堆棧可以防衛(wèi)所有把代碼植入堆棧的攻擊方法,堆棧保護(hù)可以防衛(wèi)所有改變活動記錄的方法。這兩種方法相互兼容,可以同時防衛(wèi)多種可能的攻擊。剩下的攻擊手段基本上可以依靠指針保護(hù)的方法來防衛(wèi)。