無論你是編寫銀行應(yīng)用還是游戲,如果應(yīng)用使用了網(wǎng)絡(luò),它就應(yīng)該是安全的。除了最不重要的數(shù)據(jù)之外,軟件不可能確定用戶的數(shù)據(jù)是否是機(jī)密的、尷尬的、還是危險(xiǎn)的。看似無關(guān)緊要的信息,其實(shí)很可能泄密。
由于這些原因,要始終假設(shè)應(yīng)用遇到的每個(gè)數(shù)據(jù),都可能包含銀行賬號或密碼,需要得到保護(hù)。
應(yīng)用可能遭遇到的攻擊包括:
- 窺探——第三方嗅探到傳輸中的應(yīng)用數(shù)據(jù)的攻擊。
- 中間人攻擊——第三方將自己的計(jì)算機(jī)插入到應(yīng)用和服務(wù)器之間。中間人攻擊包括:
- 窺探和網(wǎng)絡(luò)誘騙——?jiǎng)?chuàng)建偽裝成合法服務(wù)器的假服務(wù)器。
- 篡改——修改服務(wù)器和應(yīng)用之間的數(shù)據(jù)。
- 會話劫持——捕獲認(rèn)證信息,將其作用于用戶。
- 注射攻擊——該攻擊使用特定的騙術(shù)數(shù)據(jù),它能導(dǎo)致客戶端或服務(wù)器端軟件執(zhí)行未被檢查的命令。這通常發(fā)生在程序與腳本交互的時(shí)候,例如shell或者SQL數(shù)據(jù)庫服務(wù)器。
- 緩存溢出以及數(shù)字溢出——該攻擊使用特定的欺騙數(shù)據(jù),能導(dǎo)致應(yīng)用在它的地址空間的某些部分讀或?qū)?;而這些部分,是不應(yīng)該隨意執(zhí)行代碼,或泄露隱私信息,或兩者都不允許的。
本章解釋的是如何防范窺探和中間人攻擊。想要了解更多關(guān)于注射攻擊、緩存溢出,以及其他軟件安全方面的內(nèi)容,請閱讀Secure Coding Guide。
啟用TLS或SSL
傳輸層安全(Transport Layer Security, TLS)協(xié)議為基于socket通信提供數(shù)據(jù)加密,以及服務(wù)器和客戶端的認(rèn)證,來防范窺探攻擊。
OS X和iOS也提供對安全socket層(Secure Socket Layer,SSL)的支持。因?yàn)門LS是SSL的繼任者。如果兩個(gè)協(xié)議都支持,OS X和iOS在默認(rèn)情況下會使用TLS。
注意:TLS和SSL的設(shè)計(jì)主要針對于客戶-服務(wù)器模式。所以在點(diǎn)對點(diǎn)環(huán)境下使用這些協(xié)議很難確保安全通信。
安全連接到URL
通過TLS連接到URL很輕松。當(dāng)你創(chuàng)建NSURLRequest對象以提供給initWithRequest:delegate:方法時(shí),指定的https而不是http作為URL的方案。在沒有額外配置的情況下,這個(gè)連接自動(dòng)使用了TLS。
使用流數(shù)據(jù)的安全連接
你可以通過調(diào)用NSStream對象的setProperty:forKey:方法來使用TLS。指定NSStreamSocketSecurityLevelNegotiatedSSL 作為property參數(shù),指定NSStreamSocketSecurityLevelKey作為key參數(shù)。如果你需要解決兼容性錯(cuò)誤,你還可以指定更多特定的協(xié)議,例如NSStreamSocketSecurityLevelTLSv1。
使用BSD Socket的安全連接
當(dāng)進(jìn)行安全連接時(shí),如有可能,你應(yīng)該使用NSStream(如上一節(jié)所述)而不是直接使用socket。但是,如果你必須使用直接BSD socket,你必須實(shí)現(xiàn)SSL或TLS來自己進(jìn)行加密和解密。基于你平臺,有兩種方式可以做到這一點(diǎn):
- 在OS X中,或在iOS 5及更高版本中,你可以使用Security框架中的安全傳輸(Secure Transport)API來處理你的SSL和TLS握手交換、加密、以及解密。更多詳情參見Secure Transport Reference。
- 在iOS或OS X中,你可以下載開源的SSL或TLS實(shí)現(xiàn),例如OpenSSL,并把該庫(或者一部分)的變異副本包含到你的應(yīng)用程序束中(或者和你的非綁定程序在一起)。確保遵守你可能使用的第三方庫的許可條款。
注意:雖然OpenSSL庫的一個(gè)版本已經(jīng)作為OS X的一部分被包含,但OpenSSL庫不保證不同版本的OpenSSL二進(jìn)制兼容。因此,在OS X v 10.7開始,不在支持連接到OpenSSL的內(nèi)置副本。如果你想使用OpenSSL,提供庫的你自己的副本,以便你精確地控制程序連接的OpenSSL版本。
在OS X中使用其他安全協(xié)議
除了默認(rèn)的TLS安全傳輸實(shí)現(xiàn),下面的網(wǎng)絡(luò)安全協(xié)議在OS X中也是可用的:
- Kerberos協(xié)議可以通過Kerberos框架使用。這個(gè)協(xié)議提供通過網(wǎng)絡(luò)單點(diǎn)登錄認(rèn)證的支持。更多信息,閱讀read Security Overview 和 Authentication, Authorization, and Permissions Guide.
- 安全外殼(Secure Shell,SSH)協(xié)議。這個(gè)協(xié)議通常使用于終端應(yīng)用登錄遠(yuǎn)程主機(jī)。更多信息參見ssh。
- TLS的OpenSSL實(shí)現(xiàn),但是由于二進(jìn)制兼容性原因,OS X v10.7之預(yù)裝的OpenSSL庫被棄用。如果你需要OpenSSL,則提供該庫的你自己的副本,并將其靜態(tài)連接到你的應(yīng)用。
常見錯(cuò)誤
在編寫安全網(wǎng)絡(luò)代碼的時(shí)候,有一些開發(fā)者常犯的錯(cuò)誤。本部分提供為避免其中幾個(gè)錯(cuò)誤的建議。
謹(jǐn)慎對待你相信的服務(wù)器
如果應(yīng)用和服務(wù)器傳輸有潛在機(jī)密的數(shù)據(jù),要確保它對服務(wù)器的認(rèn)證,以保證它沒有被欺騙。確認(rèn)你的服務(wù)器認(rèn)證當(dāng)前的客戶端,來避免把數(shù)據(jù)提供給錯(cuò)誤的用戶。此外,確保連接使用合適的加密方式進(jìn)行了加密。
同樣的,請確保僅在必要的時(shí)候存儲數(shù)據(jù),并以執(zhí)行任務(wù)所需的最小量來提供數(shù)據(jù)。例如,為了最大限度的提高用戶個(gè)人信息的隱私性,你可以將網(wǎng)絡(luò)服務(wù)器的數(shù)據(jù)庫放在獨(dú)立的服務(wù)器上,配置為僅從你的網(wǎng)絡(luò)服務(wù)器上接收SQL請求,顯示它和整個(gè)網(wǎng)絡(luò)的連接。換句話所,使用了適當(dāng)?shù)臋?quán)限分離。
更多信息,請閱讀Secure Coding Guide中的Designing Secure Helpers and Daemons。
謹(jǐn)慎對待你相信的數(shù)據(jù)
每個(gè)應(yīng)用到處在被惡意內(nèi)容攻擊的危險(xiǎn)之中。尤其是在應(yīng)用從不受信任的服務(wù)器獲取數(shù)據(jù),或從信任的服務(wù)器獲取不信任數(shù)據(jù)的時(shí)候(例如論壇帖子)。
為了防止這樣的攻擊,應(yīng)用應(yīng)該小心的檢查所有來自網(wǎng)絡(luò)或磁盤(因?yàn)橛脩艋蛟S已經(jīng)下載了數(shù)據(jù))的數(shù)據(jù)。如果數(shù)據(jù)以某種方式表現(xiàn)出了惡意,不要像處理正常數(shù)據(jù)那樣處理它。
更多信息,參見Secure Coding Guide中的Validating Input and Interprocess Communication
要知道千里之堤潰于蟻穴
始終采取措施確保應(yīng)用在網(wǎng)絡(luò)中的內(nèi)容保持私有。雖然某些信息本身看上去是無用的,但是一個(gè)老練的攻擊者可以把該信息和其他信息進(jìn)行結(jié)合,從而可能發(fā)現(xiàn)比單條信息本身有用的多的隱私事件——該過程就是數(shù)據(jù)挖掘。
例如,如果某人想要進(jìn)入你的房間,在周六晚上在圖書館發(fā)一個(gè)帖子可能是無用的,但是連續(xù)幾個(gè)周六在相同的時(shí)間在圖書館發(fā)帖子就可能不是無用的了,因?yàn)樗鼈儽砻髁四愕牧?xí)慣。
數(shù)據(jù)甚至不需要都是針對同一件事也可以造成傷害。知道某人喜歡看特定的電視節(jié)目可能無害,但是一個(gè)人的喜好、購買的物品、以及交往的朋友組成的完整側(cè)寫,可能可以和一個(gè)人的隱私有強(qiáng)關(guān)聯(lián)性,例如宗教和性取向。一個(gè)令人印象深刻的例子(也可能不是事實(shí)),說連鎖零售企業(yè)承認(rèn),它們通過一個(gè)女孩的購買決定斷定她已經(jīng)懷孕,而女孩的父親此時(shí)還尚不知情。
身份信息泄露特別成問題。如果你的應(yīng)用泄露了手機(jī)號,其他應(yīng)用可能泄露郵政地址等等。當(dāng)攻擊者搜集到受害者足夠信息的時(shí)候,他就可以使用社交工程技術(shù)來說服第三方給他更多信息,從而導(dǎo)致信息收集的反饋循環(huán),造成毀滅性后果。
因此,應(yīng)用在任何時(shí)候進(jìn)行加密通信是非常重要的,針對所有連接,除非這樣做不可行。你永遠(yuǎn)不知道此時(shí)看起來無害的信息,在和別的看似無害的信息結(jié)合之后,就有可能發(fā)酵為危險(xiǎn)或傷害。
正確的安裝證書
當(dāng)使用TLS或SSL連接服務(wù)器的時(shí)候,如果應(yīng)用得到一個(gè)錯(cuò)誤,表示簽發(fā)了你的證書的認(rèn)證機(jī)構(gòu)是未知的,假設(shè)你從有信譽(yù)的認(rèn)證機(jī)構(gòu)獲取的證書,那么者幾乎就是意味著你的證書鏈丟失或不完整。
當(dāng)你的服務(wù)器接收到一個(gè)通過TLS或SSL加密的連接,它會提供兩樣?xùn)|西:你的服務(wù)器的SSL證書,以及完整的SSL證書鏈,從服務(wù)器的證書開始,到一個(gè)被信任的錨證書簽名的證書止,這個(gè)錨證書是被操作系統(tǒng)識別的。如果證書鏈中有證書丟失,你將得到一個(gè)錯(cuò)誤,因?yàn)殒溨械妮^早的證書無法被后面的證書驗(yàn)證。
想要查看你的服務(wù)器到底發(fā)送了什么,在終端中輸入以下命令(將www.example.com替換成你的真實(shí)域名)并按下回車鍵:
openssl s_client -showcerts -connect www.example.com:443
當(dāng)你輸入這個(gè)命令時(shí),你應(yīng)該可以看到你的服務(wù)器證書,然后時(shí)一系列中間證書。如果你沒有得到,檢查你的服務(wù)器配置。想要獲取正確的證書以便放置到你的服務(wù)器證書鏈中,請與提供服務(wù)器SSL證書的認(rèn)證機(jī)構(gòu)聯(lián)系。
永遠(yuǎn)不要禁用證書鏈驗(yàn)證(除非你自己驗(yàn)證)
禁止鏈驗(yàn)證消除了你使用安全連接可能得到的任何好處。所得到的連接不比使用沒有加密的HTTP發(fā)送請求更安全,因?yàn)樗鼪]有提供防止假服務(wù)器欺騙的保護(hù)。
如果你使用受信任的認(rèn)證機(jī)構(gòu)的服務(wù)器證書,確保你的證書正確的被安裝(查看上一部分)。
如果你臨時(shí)使用自簽名的證書,你應(yīng)該把它們添加到你的測試機(jī)器的可信任錨列表中。在OS X中,你可以使用Keychain Access(鑰匙串訪問)實(shí)用工具應(yīng)用做到這一點(diǎn)。在iOS中,你可以在程序中使用SecTrustCopyAnchorCertificates, SecTrustCreateWithCertificates, 和 SecTrustSetAnchorCertificates函數(shù)。
如果你需要特別允許的單獨(dú)的自簽名證書,或?yàn)椴煌ㄌ囟ǎ┲鳈C(jī)的簽名證書,你可以通過閱讀Overriding TLS Chain Validation Correctly來了解這樣做的安全方式。