iOS應(yīng)用網(wǎng)絡(luò)安全之HTTPS

移動互聯(lián)網(wǎng)開發(fā)中iOS應(yīng)用的網(wǎng)絡(luò)安全問題往往被大部分開發(fā)者忽略,
iOS9和OS X 10.11開始Apple也默認(rèn)提高了安全配置和要求.
本文以iOS平臺App開發(fā)中對后臺數(shù)據(jù)接口的安全通信進(jìn)行解析和加固方法的分析.

1. HTTPS/SSL的基本原理

安全套接字層 (Secure Socket Layer, SSL) 是用來實現(xiàn)互聯(lián)網(wǎng)安全通信的最普遍的標(biāo)準(zhǔn)恋昼。Web 應(yīng)用程序使用 HTTPS(基于 SSL 的 HTTP)萎羔,HTTPS 使用數(shù)字證書來確保在服務(wù)器和客戶端之間進(jìn)行安全阶淘、加密的通信冰更。在 SSL 連接中,客戶機(jī)和服務(wù)器在發(fā)送數(shù)據(jù)之前都要對數(shù)據(jù)進(jìn)行加密靠瞎,然后由接受方對其進(jìn)行解密蹂楣。

當(dāng)瀏覽器(客戶端)需要與某個安全站點建立連接時元践,先建立TCP連接(三次握手),然后再發(fā)生 SSL會話握手:

  • 瀏覽器將通過網(wǎng)絡(luò)發(fā)送請求安全會話的消息(通常請求以 https 而非 http 開頭的 URL)掸鹅。
  • 服務(wù)器通過發(fā)送其證書(包括公鑰)進(jìn)行響應(yīng)塞帐。
  • 瀏覽器將檢驗服務(wù)器的證書是否有效,并檢驗該證書是否是由其證書位于瀏覽器的數(shù)據(jù)庫中的(并且是可信的)CA 所簽發(fā)的巍沙。它還將檢驗 CA 證書是否已過期葵姥。
  • 如果證書有效,瀏覽器將生成一個==一次性的句携、唯一的==會話密鑰榔幸,并使用服務(wù)器的公鑰對該會話密鑰進(jìn)行加密。然后务甥,瀏覽器將把加密的會話密鑰發(fā)送給服務(wù)器牡辽,這樣服務(wù)器和瀏覽器都有一份會話密鑰。
  • 服務(wù)器可以使用其專用密鑰對消息進(jìn)行解密敞临,然后恢復(fù)會話密鑰态辛。

握手之后,即表示客戶端已驗證了 Web 站點的身份挺尿,并且只有該客戶端和 Web 服務(wù)器擁有會話密鑰副本奏黑。從現(xiàn)在開始,客戶機(jī)和服務(wù)器便可以使用該會話密鑰對彼此間的所有通信進(jìn)行加密编矾。這樣就確保了客戶機(jī)和服務(wù)器之間的通信的安全性熟史。

上面是一般也是應(yīng)用最普遍的單向驗證方式,由瀏覽器(客戶端)來驗證服務(wù)端的合法性窄俏;其實也可以做雙向驗證蹂匹,服務(wù)器也可以驗證瀏覽器(客戶端)的合法性,不過一般使用在銀行業(yè)務(wù)上凹蜈,比如U盾之類限寞。我們現(xiàn)在關(guān)注普遍的單向驗證方式的應(yīng)用忍啸。

2. iOS移動開發(fā)HTTPS應(yīng)用現(xiàn)狀

當(dāng)下絕大部份的移動互聯(lián)網(wǎng)項目都采用HTTP、HTTPS協(xié)議作為前后端的數(shù)據(jù)接口協(xié)議履植。而iOS開發(fā)群體中计雌,絕大部分都在項目中應(yīng)用了第三方開源的HTTP請求框架AFNetworking來快速而高效的開發(fā),畢竟快魚吃慢魚的時代嘛玫霎。AFNetworking請求HTTP接口簡直是簡單得不能再簡單了凿滤。只不過從iOS9.0開始需要設(shè)置Info.plist中App Transport Security打開非HTTP的資源加載,因為Apple默認(rèn)只允許采用經(jīng)過權(quán)威證書頒發(fā)機(jī)構(gòu)簽名的證書的HTTPS站點的訪問庶近,一切是為了安全翁脆。安全。安全拦盹。
那么我們重點來分析采用HTTPS協(xié)議的后臺接口的一般使用方式:
HTTPS的服務(wù)器配置的證書分兩大類鹃祖,一類是經(jīng)過權(quán)威機(jī)構(gòu)簽名頒發(fā)的證書,這樣證書通常是要花錢買服務(wù)的普舆,當(dāng)然現(xiàn)在也有少數(shù)機(jī)構(gòu)提供免費的證書簽名服務(wù)恬口。另一類就是服務(wù)器配置的是研發(fā)人員自己簽名生成的證書。

3.AFN調(diào)用使用權(quán)威機(jī)構(gòu)頒發(fā)證書的HTTPS接口

現(xiàn)在AFNetworking框架已經(jīng)修復(fù)了上半年爆出的SSL中間人攻擊漏洞沼侣,并強(qiáng)烈要求開發(fā)者使用公鑰綁定或者證書綁定的安全策略祖能,那么正確使用AFNetworking請求這類證書的HTTPS站點代碼很簡單如下:

    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
    policy.validatesDomainName = YES;
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.securityPolicy = policy;
    manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

對于這類證書的站點,Info.plist都不需要設(shè)置蛾洛,因為已經(jīng)是權(quán)威機(jī)構(gòu)頒發(fā)的證書了养铸,我們只需要設(shè)置驗證綁定方式和驗證域名以防止中間人攻擊,畢竟申請證書是花了錢(現(xiàn)在也有免費的申請轧膘,比如WoSign)钞螟,省事一點。

4.AFN調(diào)用使用我們自己簽名證書的HTTPS接口

對于使用我們自己簽名的證書來說谎碍,瀏覽器打開web站點也會默認(rèn)阻止訪問鳞滨,除非用戶手動把該站點加入信任列表,這個手動加入的過程其實就是不去驗證服務(wù)器的合法性蟆淀,任性的認(rèn)為服務(wù)器是可信賴的拯啦。
那么手動加入信任列表,這樣會導(dǎo)致證書的驗證過程壓根沒發(fā)生熔任,雖然可以成功訪問目標(biāo)服務(wù)器返回我們需要的數(shù)據(jù)褒链,其實,這中間很有可能返回的數(shù)據(jù)不是正真的目標(biāo)服務(wù)器返回的數(shù)據(jù)疑苔,也可能是網(wǎng)絡(luò)傳輸中間的第三者偽裝返回的數(shù)據(jù)甫匹。傳輸?shù)臄?shù)據(jù)被人竊取甚至纂改都是很可能的。

4.1 不正確的做法

瀏覽器手動加入自簽名站點到信任列表這個操作的功能相當(dāng)于iOS開發(fā)中AFNetworking的API的如下做法:

  • A 非權(quán)威機(jī)構(gòu)頒發(fā)證書的HTTPS請求一樣必須先在Info.plist設(shè)置如下:
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
  • B AFNetworking代碼設(shè)置SecurityPolicy

站點 https://tv.diveinedu.com 是我前面博客所講的配置方法配置的自簽名證書。

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    //允許非權(quán)威機(jī)構(gòu)頒發(fā)的證書
    manager.securityPolicy.allowInvalidCertificates = YES;
    //也不驗證域名一致性
    manager.securityPolicy.validatesDomainName = NO;
    //關(guān)閉緩存避免干擾測試
    manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
    [manager GET:@"https://tv.diveinedu.com/channel/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"%@",responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"%@",error);
    }];

經(jīng)過如上兩步設(shè)置之后兵迅,我們可以在iOS應(yīng)用中訪問我們采用自簽名證書的HTTPS站點了哀墓。但是這個是不安全的,因為他在沒有使用HTTPS/SSL代理和使用像Charles那樣的HTTPS/SSL代理的情況下都可以訪問服務(wù)器資源. 完全可以說是白費功夫喷兼,只能防止“君子”在網(wǎng)絡(luò)中用Wireshark之類來TCP抓包嗅探。因為畢竟還是HTTPS加密了傳輸數(shù)據(jù)了后雷。那為什么我要說這樣是白費功夫呢季惯,因為這個辦法不能防止中間人攻擊!比如用戶可以給手機(jī)設(shè)置HTTPS的SSL代理(比如Charles)臀突,完全可以在代理中看到明文數(shù)據(jù)勉抓,所以,既然用了HTTPS就要防止中間人攻擊候学,不然還不如不用HTTPS藕筋。

下面我們來看看怎么用Charles代理抓包工具所抓到的HTTPS傳輸?shù)臄?shù)據(jù):

Charles代理抓包
Charles代理抓包

上圖是在Mac上運(yùn)行Charles工具代理抓包,真機(jī)和Mac電腦同一個局域網(wǎng)梳码,并設(shè)置代理為Mac機(jī)的IP和Charles的代理端口8888隐圾,然后啟動App請求網(wǎng)絡(luò)后抓到的數(shù)據(jù)。是不是很意外啊掰茶。HTTPS的數(shù)據(jù)也抓出明文了暇藏。
顯然這樣是非常不安全的,那么當(dāng)我們使用自簽名證書的時候濒蒋,我們該如何來在App端(客戶端)嚴(yán)格的驗證服務(wù)器的合法性呢盐碱?

4.2 正確的做法

我們要在App端嚴(yán)格驗證服務(wù)器的合法性,防止網(wǎng)絡(luò)中間的代理或者防火墻進(jìn)行中間人的攻擊和證書欺騙,那么我們需要把服務(wù)器配置的證書打包到客戶端程序中(私鑰留服務(wù)器不要分發(fā)不用泄露,非常重要),在代碼里去讀取該證書/公鑰信息和服務(wù)器返回的進(jìn)行匹配驗證.
在iOS開發(fā)中,從Xcode7和iOS9開始,Apple提升了App的網(wǎng)絡(luò)安全性,App默認(rèn)只能進(jìn)行對采用權(quán)威機(jī)構(gòu)簽名頒發(fā)證書的Web站點進(jìn)行訪問(信任的HTTPS),而自簽名的證書的HTTPS站點也被列為屬于例外,所以我們需要在App的Info.plist中單獨為我們的域名設(shè)置Exception Domains"白名單",而不是打開Allow Arbitrary Loads全部放開,設(shè)置信息如下:

Xcode的Info.plist中NSAppTransportSecurity設(shè)置
Xcode的Info.plist中NSAppTransportSecurity設(shè)置
   <key>NSAppTransportSecurity</key>
   <dict>
       <key>NSExceptionDomains</key>
       <dict>
           <key>tv.diveinedu.com</key>
           <dict>
               <key>NSExceptionAllowsInsecureHTTPLoads</key>
               <true/>
           </dict>
       </dict>
   </dict>

這樣就不像上面那個方法那樣一刀切全部放開, 而是單獨為某個域名放開設(shè)置.當(dāng)然上面也可以使用放開全部的設(shè)置NSAllowsArbitraryLoadstrue.但是我建議使用白名單.

除此之外,要做到嚴(yán)格驗證防止像Charles那樣的中間人代理抓包,AFNetworking代碼應(yīng)該用如下設(shè)置:

   //服務(wù)器端配置的包含公鑰的證書分發(fā)到客戶端后,需要轉(zhuǎn)換為DER格式的證書文件.
   //openssl x509 -outform der -in tv.diveinedu.com.crt -out tv.diveinedu.com.der
   NSString *certFilePath = [[NSBundle mainBundle] pathForResource:@"tv.diveinedu.com" ofType:@"der"];
   NSData *certData = [NSData dataWithContentsOfFile:certFilePath];
   NSSet *certSet = [NSSet setWithObject:certData];
   AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey withPinnedCertificates:certSet];
   policy.allowInvalidCertificates = YES;
   AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
   manager.securityPolicy = policy;
   //關(guān)閉緩存避免干擾測試
   manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
   [manager GET:@"https://tv.diveinedu.com/channel/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
       NSLog(@"%@",responseObject);
   } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
       NSLog(@"%@",error);
   }];

上面的代碼能夠驗證服務(wù)器身份在沒有使用代理的時候可以正常訪問服務(wù)器的資源,但是一旦用戶給手機(jī)網(wǎng)絡(luò)設(shè)置使用了如Charle那樣的HTTPS/SSL代理服務(wù),則會出現(xiàn)服務(wù)器證書驗證失敗,SSL網(wǎng)絡(luò)連接會斷開,老板再也不用擔(dān)心數(shù)據(jù)接口被人抓包或者代理給扒出來了.故達(dá)到防止中間人攻擊的效果.

當(dāng)使用Charles SSL代理時Xcode調(diào)試終端出錯信息圖:

Xcode調(diào)試終端出錯信息
Xcode調(diào)試終端出錯信息

代理服務(wù)器Charles那邊的出錯信息圖:

Charles那邊的出錯信息
Charles那邊的出錯信息

最后,關(guān)于iOS9和OSX 10.11 開發(fā)時,Xcode的Info.plist的NSAppTransportSecurity詳細(xì)設(shè)置方法請參考Apple官方文檔:
NSAppTransportSecurity Reference

更多iOS/Linux開發(fā)資料和視頻資源請去:
戴維營學(xué)院視頻站
移動開發(fā)潛心俱樂部

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市沪伙,隨后出現(xiàn)的幾起案子瓮顽,更是在濱河造成了極大的恐慌,老刑警劉巖围橡,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暖混,死亡現(xiàn)場離奇詭異,居然都是意外死亡某饰,警方通過查閱死者的電腦和手機(jī)儒恋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來黔漂,“玉大人诫尽,你說我怎么就攤上這事【媸兀” “怎么了牧嫉?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我酣藻,道長曹洽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任辽剧,我火速辦了婚禮送淆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怕轿。我一直安慰自己偷崩,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布撞羽。 她就那樣靜靜地躺著阐斜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诀紊。 梳的紋絲不亂的頭發(fā)上谒出,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機(jī)與錄音邻奠,去河邊找鬼笤喳。 笑死,一個胖子當(dāng)著我的面吹牛碌宴,可吹牛的內(nèi)容都是我干的莉测。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼唧喉,長吁一口氣:“原來是場噩夢啊……” “哼捣卤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起八孝,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤董朝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后干跛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體子姜,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年楼入,在試婚紗的時候發(fā)現(xiàn)自己被綠了哥捕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡嘉熊,死狀恐怖遥赚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阐肤,我是刑警寧澤凫佛,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布讲坎,位于F島的核電站,受9級特大地震影響愧薛,放射性物質(zhì)發(fā)生泄漏晨炕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一毫炉、第九天 我趴在偏房一處隱蔽的房頂上張望瓮栗。 院中可真熱鬧,春花似錦瞄勾、人聲如沸遵馆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秆撮。三九已至四濒,卻和暖如春职辨,著一層夾襖步出監(jiān)牢的瞬間盗蟆,已是汗流浹背舒裤。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工喳资, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腾供。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像伴鳖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子榜聂,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容