2 代碼安全(Code Security)
沒有完美的軟件。盡管許多缺陷是由于設計錯誤,一些最具破壞性的缺陷是由實現(xiàn)錯誤引起的。設計缺陷和執(zhí)行缺陷可以損害的數(shù)據(jù),可以使您的軟件行為不當。攻擊實現(xiàn)缺陷有時也會導致你的軟件來執(zhí)行攻擊者提供的任意的二進制代碼撮抓。
阻止這些攻擊,威脅模型只能幫你到此。他們識別的部分基礎設施可能被合理攻擊,但是他們不確定具體這些碎片可能是攻擊的方法。
2.1代碼硬化(Code Hardening)
代碼硬化指修復安全漏洞的代碼本身(而不是設計錯誤)署驻。本質上,代碼硬化就像修理城堡的墻上的壞的砂漿以防止攻擊者從此進來,加固船的船尾修復泄漏,或隱藏一個統(tǒng)治者的秘密,這樣他或她不能被敲詐成為一個傀儡統(tǒng)治者。
這里有一些代碼硬化的技術:
- 添加來驗證輸代碼入,以防止整數(shù)溢出绊序。
- 代替任何不安全的字符串函數(shù)調用硕舆,通過調用緩沖區(qū)大小感知(buffer-size-aware)的方法防止緩沖區(qū)溢出。
- 盡可能避免傳遞數(shù)據(jù)到解釋器(interpreters)骤公。當必須要使用解釋器時,通過一個安全的方式傳遞數(shù)據(jù)抚官。
為了防止在SQL查詢命令注入攻擊,使用參數(shù)化api(或手動引用字符串如果參數(shù)化api不可用)。
避免POSIX(可移植操作系統(tǒng)接口) - 設置合理的環(huán)境變量的值(PATH, USER,等等),不基于他們的值進行安全決策阶捆。
- 修改bug導致競爭條件凌节;這些可能導致不正確的行為(或更糟)。
在本章結束時,你會發(fā)現(xiàn)一個鏈接到文檔更詳細地描述這些技術,連同其他code-hardening技術洒试。
2.2代碼簽名(Code Signing)
代碼簽名技術保證可執(zhí)行代碼的可靠性倍奢。通過簽署你的代碼,操作系統(tǒng)可以驗證應用程序沒有被其他軟件修改,可以驗證更新應用程序確實是作者發(fā)布的。其他技術,如鑰匙鏈和應用沙盒,利用這個簽名來更好地保護用戶的數(shù)據(jù)垒棋。
了解細節(jié),不過,你得學習更多的概念卒煞。出于這個原因,在第4章加密服務(Cryptographic Services)重新審視代碼簽名。
2.3 最小特權原則(Principle of Least Privilege)
最小特權原則聲明一段代碼,在某種程度上實用叼架、準確運行需要的權限,沒有更多畔裕。
最接近的模擬物理世界中指定某些領域某些活動,并且只有當他們有一個合法的需要執(zhí)行這些活動時才允許人們進入這些地區(qū)。例如,在一次會議上,技術人員不需要訪問演講者支持中心,演講者(通常)也不需要訪問后臺區(qū)域乖订。
幾乎以相同的方式,你的軟件不應該承擔或授予他人任何比必要做特定的工作更多的權限扮饶。例如,應用程序不應該:
- 在不是確實必要的情況下請求權限提升
- 部分應用程序包放寬權限
- 不必要的網(wǎng)絡連接
- 在不必要的網(wǎng)絡端口上監(jiān)聽連接
- 無意的在公共網(wǎng)絡接口監(jiān)聽連接
- 在沒有用戶指示的情況下公開可寫權限的文件夾讀或寫文件
這些只是幾個例子。因為這些活動是隨附于你的應用的主要行為, 當您添加新代碼時有規(guī)律的執(zhí)行威脅建模是至關重要的乍构。
2.4 應用沙盒(App Sandboxing)
對父母來說,沙盒是一個安全的港灣,在這里孩子們可以玩,而不需要擔心他們受傷甜无。這是一個比較封閉的,安全的環(huán)境,遠離可能會傷害到他們的事物。只要孩子們在沙箱內(nèi),他們不能(容易)導致沙箱之外的惡作劇哥遮。
同樣,在計算機中,一個沙箱的好處不僅限于糟糕的應用程序岂丘。任何包含安全漏洞的應用程序如果利用得當都可以“變壞” ,可能導致應用程序運行任意代碼。因此,在計算,沙箱應該被廣泛應用到所有app昔善,確保如果他們被侵害不能造成太多的損害元潘。
為了實現(xiàn)這一目標,沙箱限制應用程序的功能來匹配其預期行為(如使用的api,在某些情況下, 應用程序的作者通過一系列附加權利要求)。
因此,在計算中君仆,沙箱更像鄰里監(jiān)督組織監(jiān)督違法程序的眼睛翩概。如果有人出現(xiàn)行為可疑,鄰居們可以采取行動牲距。以類似的方式,沙箱環(huán)境允許應用程序做通常會做的事情。然而,如果踩到紅線的,操作失敗,在某些情況下,這個進程會被立刻殺死钥庇。
2.5 權限分離(Privilege Separation)
在一個理想世界中,根據(jù)最小特權原則編寫軟件將會是簡單的;用戶授予做一份工作每個流程所需的足夠的特權,沒有更多牍鞠。然而,這種方法在實踐中可能是一個挑戰(zhàn),特別是當工作的性質定義不明確的時候。
一個真實世界的例子,清潔工需要能夠把垃圾拿出去评姨。清潔的位置通常并不需要一個高度安全許可难述。假設有一個垃圾桶在一個房間里充滿了絕密文件。因為這垃圾桶表面上是清潔工的職責,工作相當廣泛的最小特權清潔工需要一個高度安全的許可吐句。更好的解決方案是將垃圾桶放到門外胁后。或者,一個已經(jīng)有了必要許可的員工可以在一天結束的時候把垃圾桶拿出來嗦枢。
在計算機中,此問題的解決方案是特權分離攀芯,將軟件分成多個部分,每一塊單獨需要較少的權限,這樣可以免受應用程序的其他部分,工具,或守護進程的不當使用。這個分離塊稱為信任邊界(trust boundary)文虏。
例如,一個字處理器通過網(wǎng)絡訪問幫助文件的網(wǎng)絡部分可能分離到一個單獨的幫助文件下載應用侣诺。主要應用需要仔細檢查從這個助手發(fā)回的數(shù)據(jù),既要確保它在運輸途中未被篡改,并確這個助手如果被入侵并不能輕易攻擊的主應用程序。
重要:助手和主應用之間的不信任必須是相互的氧秘。網(wǎng)絡助手在前面的例子必須仔細審查主要應用程序的請求,確保:
- 所有的請求都去向正確的服務器
- 所有的請求資源的請求應用程序都被授權
- 只在適當?shù)臅r候進行HTTP重定向
沒有這些檢查,攻擊者破壞的主要應用程序可能使用網(wǎng)絡幫助轉發(fā)一份用戶的數(shù)據(jù)到其他地方年鸳。
特權分離是通過編寫一個助手,守護進程,或代理,目的是使它在軟件的另一部分工作丸相。助手,守護進程,或代理人可能沙箱封裝化的,未沙盒封裝化得或享有特權的搔确。
- ?沙盒化的助手,守護進程,或代理權限少于一個普通用戶運行的應用程序。它可能還是比調用應用程序更多的權限,然而,由于調用者可能在一個更嚴格的沙箱灭忠。
- 未沙盒化的助手,守護進程,或代理和用戶具有相同的權限妥箕。然而,由于調用應用程序可能在沙箱中運行,這個未沙盒化的助手可能比調用者有更多的特權。
- 特權助手更舞、守護進程或代理運行另一個更廣泛的用戶權限(經(jīng)常作為根用戶,或超級用戶,這本質不限制操作)。
特權助手無法創(chuàng)建在一個沙箱環(huán)境;然而,他們在使環(huán)境更有用上發(fā)揮關鍵的作用坎吻。例如,一個特權代理(特權只因為它是運行在沙箱)使用操作系統(tǒng)向沙箱應用提供一系列的服務,如powerbox,顯示一個“打開文件”對話框代表應用程序然后暫時將所選文件添加到應用程序的沙箱缆蝉。
因為不同的特權助手、守護進程或代理有可能允許調用者明顯違反了權限范圍,它必須用這種方式限制其調用者能做什么瘦真。例如,powerbox允許應用程序訪問文件應用程序的容器目錄之外,但它用戶采取一個明確的行動來表示同意刊头。
OS X v10.7介紹了XPC服務API來創(chuàng)建沙箱助手應用程序特定于一個單一的應用程序。這些helper應用程序可以與主要應用有不同的權限诸尽。OS X v10.8后來還提供NSXPC API,這使得特權分離的過程更透明,讓主應用程序遠程調用指定的方法在特定的輔助應用程序中的對象,反之亦然原杂。