iOS 網(wǎng)絡(luò)數(shù)據(jù)安全(防止抓包)

A.首先 淺談http宋梧、https與數(shù)據(jù)加密

ip、端口蜻懦、http協(xié)議

下面用一個例子來介紹客戶端與服務(wù)器在應(yīng)用層的通訊流程

  • 有兩個很好的朋友间螟,小客(客戶端)和小服(服務(wù)端),他們經(jīng)常需要寫信交流逸吵,那么他們寄信需要哪些步驟呢凶硅?

  • 1.小客需要有自己的家庭住址(IP地址)和小服的家庭住址,這樣郵差才知道把信寄到哪里扫皱,以及小服收到信之后足绅,要把返回的信息寄回哪里。

  • 2.信中要包含小客要告訴小服的內(nèi)容韩脑,這些內(nèi)容通常以Json字符串的形式傳播氢妈,Json因其輕便簡單,已漸漸替代掉了XML段多,假設(shè)小客給小服寫了一段話:你那邊天氣怎么樣首量,他就可以包裝一個json:{"question":"你那邊天氣怎么樣"},寫到信中發(fā)送給小服。

  • 3.郵差拿到這封信就可以根據(jù)對方的ip地址加缘,寄給小服鸭叙,小服收到信之后,通過來源的ip地址就可以將自己的回答{"answer":"今天是晴天"}通過郵差返回給小客生百,整個通過寄信交流的流程就結(jié)束了递雀。

  • 我們來仔細(xì)思考上述流程,在上述流程中蚀浆,小客給小服寄信就是【請求】缀程,小服回復(fù)小客就是【響應(yīng)】,在http中市俊,他們總是一對存在的杨凑。

  • 【什么是內(nèi)網(wǎng)(局域網(wǎng))?】小客和小服所在的小區(qū)摆昧,就可以理解為兩個不同的內(nèi)網(wǎng)撩满,我們現(xiàn)實生活中一般通過路由器連接至外網(wǎng)(公網(wǎng)),這里的路由器可以理解為小區(qū)大門绅你,所有的信都要從大門寄往其他的小區(qū)伺帘,大門外就是【因特網(wǎng)】,因特網(wǎng)把各個小區(qū)連接到了一起忌锯。

  • 【什么是IP地址伪嫁?】IP地址可以看作是每個網(wǎng)絡(luò)參與者的唯一地址,就像現(xiàn)實生活中我們的收件地址一樣偶垮,包含省市區(qū)詳細(xì)地址門牌號等信息张咳,這樣才可以精確地信寄到目的地,但是如果是在局域網(wǎng)中呢似舵,如果收件人和寄件人身處通過小區(qū)脚猾,那他們的ip地址其實只需要包含樓棟和門牌號即可,如(5#1004)砚哗,ip地址亦然龙助。IPv4地址中預(yù)留了3個IP地址段,作為私有地址频祝,共家庭泌参、企業(yè)、學(xué)校等內(nèi)部組網(wǎng)使用常空,最常見的是C類地址段192.168.0.0-192.168.255.255沽一,192.168.1.1是大多數(shù)路由器的ip地址,也就是小區(qū)大門的ip地址漓糙,這樣就可以連接192.168.1.1(不包含)-192.168.1.255共254臺設(shè)備铣缠,一般家庭路由器使用已經(jīng)足夠了。這樣就會導(dǎo)致不同的局域網(wǎng),可能有相同的ip地址蝗蛙,就像不同的小區(qū)都有(5#1004)一樣蝇庭,但是信息仍然可以準(zhǔn)確送達(dá),正是因為192.168.x.x是局域網(wǎng)地址捡硅,如果需要跨小區(qū)交流還需要公網(wǎng)地址哮内。

  • 【什么是端口?】端口是服務(wù)端的概念壮韭,如果ip地址指的是家庭住址的話北发,那么端口就是這個家中你需要把信送達(dá)的那個人。

  • 什么是域名喷屋?ip地址是一串?dāng)?shù)字加點拼接的地址琳拨,用戶通常很難記住,域名就相當(dāng)于是ip地址的別名屯曹,幫助用戶更好地記住需要訪問網(wǎng)站的地址狱庇,www.baidu.com 就比14.215.177.38直觀得多。

  • 【什么是域名解析恶耽?】域名解析值的是從域名解析到ip地址的過程密任,域名解析是由DNS服務(wù)器完成的,當(dāng)我們訪問www.baidu.com時偷俭,瀏覽器會像DNS服務(wù)器提交域名批什,DNS服務(wù)器返回這個域名的ip地址給瀏覽器,我們看到的是通過域名訪問社搅,實際上所有的通訊都是通過ip進(jìn)行的,但是這就引發(fā)了一個常見的問題乳规,就是DNS劫持形葬,黑客通過DNS緩存感染或信息劫持等方式,將錯誤的ip放回給用戶暮的,導(dǎo)致用戶被引導(dǎo)到其他不良網(wǎng)站笙以,或者插入廣告等不法目的。

  • 【什么是請求頭冻辩、響應(yīng)頭猖腕、請求體、響應(yīng)體】恨闪?請求頭用于攜帶附加的信息倘感,GET請求和POST請求都包含請求頭,請求頭通常包含:【Host】目標(biāo)地址的地址+端口咙咽;【User-Agent】瀏覽器的類型老玛;【Content-Length】請求消息內(nèi)容的長度;【Content-type】請求消息內(nèi)容的類型,如application/x-www-form-urlencodedapplication/json蜡豹;等麸粮。

http傳輸安全

在上個例子中,小客和小服在溝通中存在一個很大的安全隱患镜廉,假設(shè)郵差在送信過程中被人攔截下來弄诲,并篡改了信的內(nèi)容,這樣就會導(dǎo)致隱私泄露和信息被惡意修改問題娇唯,并且小客和小服完全不知道發(fā)生了什么齐遵。我們?nèi)绻筯ttp請求更安全呢?

使用http請求真的那么不安全嗎视乐,攻擊者到底是如何攔截我發(fā)出的請求的洛搀?

  • 請求的傳輸就和上方類比的“送信”是相似的,我們的手機佑淀、電腦發(fā)送的網(wǎng)絡(luò)請求送設(shè)備的網(wǎng)卡發(fā)出后留美,一般第一步進(jìn)過的就是路由器(網(wǎng)關(guān)),由路由器將請求傳遞到外網(wǎng)中伸刃。

  • 【抓取途徑路由器的流量】當(dāng)你連接他人的路由器谎砾,那么你發(fā)送的所有請求都會經(jīng)過這個路由器,最便捷的可以通過路由器系統(tǒng)自帶的tcpdump抓取數(shù)據(jù)幀捧颅,也可以將路由器鏡像到電腦景图,通過Wireshark對電腦的網(wǎng)卡進(jìn)行抓包,方式林林總總碉哑,但都能達(dá)到同一個目的挚币,抓取通過這個路由器的流量或是篡改數(shù)據(jù)。

  • 【ARP欺騙】了解什么是ARP需要我們先知道什么是ip和MAC地址的關(guān)系扣典,當(dāng)我們的設(shè)備聯(lián)網(wǎng)時會獲得一個在這個局域網(wǎng)內(nèi)唯一的ip地址妆毕,如果沒有指定ip地址,我們的設(shè)備每次聯(lián)網(wǎng)ip地址都可能發(fā)生改變贮尖,因此ip地址僅代表這個時候笛粘,這臺設(shè)備在網(wǎng)絡(luò)中的位置,它只代表一個別名湿硝,MAC地址也叫作物理地址薪前,類似設(shè)備的身份證號,是設(shè)備的唯一標(biāo)識关斜,不管在何種網(wǎng)絡(luò)環(huán)境下示括,MAC地址都是不會改變的。ARP協(xié)議用于將IP地址轉(zhuǎn)換為MAC地址痢畜。當(dāng)局域網(wǎng)內(nèi)的兩臺設(shè)備需要通訊例诀,表面上看它們是通過ip知道對方的位置進(jìn)行通訊随抠,實際上它們需要先根據(jù)ip找到對方的MAC地址,網(wǎng)絡(luò)設(shè)備是通過MAC地址進(jìn)行通訊的繁涂,而非ip地址拱她。使用ARP欺騙的攻擊者通過偽造數(shù)據(jù)包ARP報文,向局域網(wǎng)內(nèi)的網(wǎng)絡(luò)設(shè)備廣播扔罪,將自己的MAC地址偽裝成網(wǎng)關(guān)的MAC地址秉沼,使得局域網(wǎng)內(nèi)的網(wǎng)絡(luò)設(shè)備的ARP緩存表中網(wǎng)關(guān)IP對應(yīng)的MAC地址變?yōu)樽约涸O(shè)備的MAC地址,此時其他設(shè)備的所有請求都將發(fā)往攻擊者的設(shè)備上矿酵,若攻擊者對這些請求轉(zhuǎn)發(fā)至網(wǎng)關(guān)或外網(wǎng)唬复,則請求正常,否則其他設(shè)備將全部斷網(wǎng)全肮。

    攻擊者通過ARP欺騙將自己的設(shè)備偽造成網(wǎng)關(guān)敞咧,使得連接這個路由器的所有網(wǎng)絡(luò)設(shè)備的請求都經(jīng)過自己的設(shè)備,通過這個方法辜腺,攻擊者無需是路由器的所有者休建,也無需或者路由器的訪問權(quán)限即可捕獲甚至修改局域網(wǎng)內(nèi)網(wǎng)絡(luò)設(shè)備的所有請求。

  • 【用戶自己進(jìn)行抓包】用戶可以通過代理抓包(如Charles评疗,Burp等工具)测砂,或WireShark等對自己設(shè)備安裝的應(yīng)用程序或網(wǎng)頁進(jìn)行抓包,若開發(fā)者未對數(shù)據(jù)進(jìn)行加密百匆,則用戶可以輕易對數(shù)據(jù)進(jìn)行篡改砌些,例如有一款打卡App,通過獲取用戶當(dāng)前的經(jīng)緯度并上傳至服務(wù)器以判定該用戶是否在規(guī)定范圍內(nèi)打卡加匈,若請求數(shù)據(jù)為明文的存璃,則用戶可以修改經(jīng)緯度并提交給服務(wù)器,服務(wù)器仍然會認(rèn)可這個打卡操作雕拼,這樣打卡就被輕松破解了有巧。

【數(shù)據(jù)加密】

  • 假設(shè)小客給小服發(fā)了一句 hello,并且他們制定了一個加密規(guī)則悲没,那就是對他們之間的聊天進(jìn)行加密,以防止聊天消息被竊取和篡改男图,這個加密規(guī)則是:把明文中的每一個字母后移一位示姿,生成密文,這樣就生成了密文:ifmmp逊笆,顯然若信件途中被攔截下來栈戳,攔截者是看不懂內(nèi)容的,如果它對內(nèi)容進(jìn)行篡改难裆,小服拿到密文把每一位字母前移一位子檀,會發(fā)現(xiàn)不是正常的單詞镊掖,就會發(fā)覺信息已被篡改。
  • 但是生活中商業(yè)化的加密方式肯定比上述復(fù)雜得多褂痰,以下列舉幾個比較常用的加密方式
  • 【對稱加密】如AES亩进、DES加密,對稱加密的意思是加密和解密的密鑰都是一樣的缩歪,例如使用密鑰12345對字符串進(jìn)行加密归薛,那就需要使用密鑰12345對這個字符串解密以獲得明文,密鑰就像是鑰匙一樣匪蝙,可以加鎖主籍,也可以解鎖。
  • 【非對稱加密】如RSA逛球、ECC橢圓曲線加密算法千元,非對稱加密需要兩個密鑰(一對密鑰),公鑰:公開密鑰颤绕,私鑰:私有密鑰幸海,使用公鑰對數(shù)據(jù)進(jìn)行加密,只能使用對應(yīng)的私鑰才能解鎖屋厘,私鑰是保密的涕烧,公鑰是公開的。
  • 【Hash算法】如MD5汗洒、SHA议纯,MD5使用較為廣泛,它可以將一個任意長度的字符串生成16字節(jié)的散列值溢谤,不同的字符串瞻凤,哪怕只有一個字母不同,他們的散列值都是完全不同的世杀,相同的字符串有相同的散列值阀参,并且無法根據(jù)散列值倒推回原來的明文,但是因為使用MD5生成的密文與明文一一對應(yīng)瞻坝,因此只要知道這一對明文和密文蛛壳,就可以輕松根據(jù)密文推出明文,如“123”MD5加密后為的32位密文為“202cb962ac59075b964b07152d234b70”所刀,那已知密文“202cb962ac59075b964b07152d234b70”即可推出它的明文為123衙荐,即使近年已證明MD5已被攻破,并推出了MD6浮创,但目前而言忧吟,MD5仍被廣泛用于密碼不可逆加密,請求驗簽等斩披。

【數(shù)據(jù)加密示例】

  • 【AES加密】已知明文{"data":"hello"}溜族,且客戶端與服務(wù)端私下約定好key為12345讹俊,則使用AES加密出來的密文為(U2FsdGVkX189vc7hUqp6f8FhQMMUMI9GFiWOtChSEM3u4jDRLDJiwm6lee3MjmqT),則攔截者必須知道雙方約定好的密鑰才能獲得明文煌抒,如果攔截者對密文進(jìn)行篡改仍劈,服務(wù)端則無法正常解析,篡改內(nèi)容不會被信任摧玫。

  • 【RSA加密】已知明文{"data":"hello"}耳奕,客戶端保存這公鑰12345,服務(wù)端保存私鑰09876诬像,則使用公鑰加密的密文只能通過私鑰來解密屋群,且由于公鑰可以根據(jù)私鑰計算出來,因此理論上只需要私鑰就可以進(jìn)行加解密坏挠,但是由于很多情況下私鑰放在客戶端并不安全芍躏,因此一般是客戶端存放公鑰,服務(wù)端存放私鑰降狠。

  • 【MD5加密】由于MD5加密是不可逆的对竣,因此一般不會直接對數(shù)據(jù)進(jìn)行加密,因為客戶端使用MD5對整個數(shù)據(jù)進(jìn)行加密了榜配,服務(wù)端也無法獲取明文否纬,因此MD5加密一般用于用戶密碼加密和驗簽,為了提高M(jìn)D5的安全性蛋褥,一般在使用MD5的時候會進(jìn)行“加鹽”操作临燃,例如明文是12345,鹽是sajhdakj烙心,那么實際上就是將12345sajhdakj進(jìn)行MD5加密膜廊,這樣攻擊者很難通過密文倒推出明文,如今很多網(wǎng)站都可以解密MD5淫茵,實際上絕大多數(shù)都是存儲著明文和密文的鍵值對爪瓜,以便第一時間通過密文倒推明文。

    【用戶密碼加密】假設(shè)用戶進(jìn)行登錄操作匙瘪,發(fā)送請求{"account":"123","pwd":"456"}铆铆,若此請求被攻擊者攔截,攻擊者可以輕松獲得其密碼并登錄其賬號丹喻,更為嚴(yán)重的事薄货,很多用戶不同平臺使用的密碼相同,這樣就會極大地危害用戶信息安全驻啤,因此一般都會對用戶的密碼“456”進(jìn)行加鹽的MD5操作,這樣攻擊者拿到密文無法推出明文荐吵,也就保證了用戶的賬戶安全骑冗,對于服務(wù)端來說赊瞬,其實沒有必要得知用戶密碼的明文满粗,只要在注冊的時候?qū)⒂脩裘艽a的密文存到數(shù)據(jù)庫中豹障,在用戶登錄的時候比較密文即可。因此大多數(shù)網(wǎng)站都無法提供密碼找回服務(wù)(因為他們也不知道用戶的密碼明文是什么)判哥,只能提供密碼重置服務(wù)遥倦。

    【請求驗簽】假設(shè)用戶進(jìn)行登錄操作谤绳,發(fā)送請求{"account":"123","pwd":"456"},通過將json轉(zhuǎn)化為特定的格式袒哥,如account=123&pwd=456(一般會拼接一段固定的字符串【鹽】)缩筛,并對其進(jìn)行md5加密,將加密后的MD5值放在sign字段中堡称,就得到{"account":"123","pwd":"456","sign":"MD5加密后的值"}瞎抛,服務(wù)器拿到這個json的時候,將sign以外的key和value進(jìn)行與客戶端相同的加密操作却紧,并比對加密出來的結(jié)果與sign內(nèi)容的值桐臊,若相同,則可以認(rèn)為account和pwd未被篡改晓殊,可信任這個請求断凶,若不同,則代表必然有信息被篡改巫俺,則廢棄這個請求认烁。

【https】

  • https是指http+SSL/TLS協(xié)議,在傳輸過程中對數(shù)據(jù)進(jìn)行加密识藤,開發(fā)者無法自己設(shè)定加密邏輯

  • 【https加密大致流程】服務(wù)端與客戶端通過https進(jìn)行通訊砚著,數(shù)據(jù)加密使用到了非對稱加密(一般是RSA)和對稱加密,大致流程如下:

    1.客戶端向服務(wù)端發(fā)起https請求痴昧。

    2.服務(wù)端將之前生成的一對RSA密鑰中的公鑰返回給客戶端稽穆。

    3.客戶端隨機生成一個對稱加密(如AES)的key(密鑰),并通過服務(wù)器提供的RSA公鑰赶撰,對這個key進(jìn)行加密舌镶,將加密后的對稱加密key發(fā)送給服務(wù)端。

    4.服務(wù)端拿到這個對稱加密后的key豪娜,并通過自己的私鑰對這個密文進(jìn)行解密餐胀,拿到與客戶端進(jìn)行對稱加密通訊的明文key。

    5.服務(wù)端與客戶端通過這個key加密密文進(jìn)行通信瘤载。

  • 【疑問】為什么這個流程這么繁瑣否灾,服務(wù)端直接把對稱加密的密鑰給客戶端不就可以了嗎?答:服務(wù)端把對稱加密密鑰給客戶端的途中鸣奔,可能被中間人攔截墨技,中間人獲得對稱加密的key之后惩阶,加密形同虛設(shè)。

    上述流程真的就萬無一失了嗎扣汪?顯然還有很大的漏洞断楷!服務(wù)端將RSA非對稱加密的公鑰發(fā)送給客戶端的途中,中間人可以將公鑰攔截下來崭别,并提前自己創(chuàng)建一對RSA密鑰冬筒,將自己的RSA公鑰發(fā)送給客戶端,客戶端通過這個被篡改的RSA公鑰對自己隨機生成的對稱加密密鑰進(jìn)行加密后茅主,發(fā)送給服務(wù)端舞痰,在這個途中,中間人可以將此密文攔截下來暗膜,并通過自己的RSA私鑰進(jìn)行解密(因為客戶端實際上是用自己的公鑰加密的)匀奏,此時中間人可以拿到明文的對稱加密密鑰,此時中間人通過先前截獲的服務(wù)端的RSA公鑰對此對稱密鑰進(jìn)行加密学搜,并發(fā)送給服務(wù)端娃善,服務(wù)端通過自己的RSA私鑰可以獲取到對稱加密密鑰的明文,此時中間人已經(jīng)悄悄獲取了二者將來進(jìn)行的對稱加密通訊的密鑰瑞佩,就可以輕松解密和篡改二者的通訊信息了聚磺。

  • 【如何解決上述問題】實際上https通訊過程中還有一個極為重要的角色:CA(Certificate Authority)數(shù)字證書頒發(fā)機構(gòu),CA實際上是指多個權(quán)威的證書頒發(fā)機構(gòu)炬丸,他們會生成一對公鑰和私鑰瘫寝,并將公鑰存儲于操作系統(tǒng)和瀏覽器中,通過CA的介入可以完美解決稠炬,CA介入以后的加密流程如下:

    1.客戶端向服務(wù)端發(fā)起https請求焕阿。

    2.服務(wù)端將之前生成的一對RSA密鑰中的公鑰(通過CA的RSA私鑰加密后),返回給客戶端首启。

    3.客戶端拿到加密后的服務(wù)器公鑰暮屡,通過瀏覽器或系統(tǒng)中預(yù)先安裝好的公鑰進(jìn)行解密,若可以解密毅桃,則https請求可以繼續(xù)進(jìn)行褒纲,客戶端順利拿到服務(wù)器公鑰的明文,并使用這個公鑰對隨機生成的對稱加密密鑰加密钥飞,將加密后的對稱加密key發(fā)送給服務(wù)端莺掠。若無法解密,則代表公鑰被篡改读宙,https請求終止彻秆,且瀏覽器會顯示warning。

    4.服務(wù)端拿到這個對稱加密后的key,并通過自己的私鑰對這個密文進(jìn)行解密唇兑,拿到與客戶端進(jìn)行對稱加密通訊的明文key墓律。

    5.服務(wù)端與客戶端通過這個key加密密文進(jìn)行通信。

    6.此時這個加密后的公鑰若被中間人攔截幔亥,并且由于CA的公鑰是公開的,因此中間人可以解密并獲取服務(wù)器的公鑰明文察纯,但是他無法將其替換為自己的公鑰帕棉,因為替換之后,他需要CA的私鑰來對自己的公鑰來進(jìn)行加密饼记,否則直接將明文的公鑰或者是使用他人私鑰加密后的公鑰提交給客戶端香伴,由于客戶端中沒有可以解密的公鑰,https請求將終止具则。

  • 【另一個疑問】為什么大多數(shù)的抓包工具即纲,在我的手機安裝一個根證書并讓我信任后,就可以抓到https請求博肋?

    通過以上的加密流程分析低斋,可以很快地解決上述問題。

    1.安裝根證書并信任匪凡,實際上就是讓系統(tǒng)和瀏覽器認(rèn)定所安裝的根證書的CA身份膊畴,根證書中包含著一對公鑰和私鑰。

    2.安裝根證書后病游,中間人(抓包程序)會先對服務(wù)端返回給客戶端的經(jīng)過CA私鑰加密后的服務(wù)端公鑰唇跨,通過CA公鑰進(jìn)行解密,此時就拿到了服務(wù)端公鑰的明文衬衬,此時中間人通過自己創(chuàng)建的一個證書(證書中包含私鑰和公鑰买猖,這個證書和讓用戶安裝在手機上的根證書一致),中間人將服務(wù)器的公鑰篡改為自己的公鑰滋尉,通過其中的私鑰對這個公鑰進(jìn)行加密玉控,并發(fā)送給客戶端,客戶端拿到這個被篡改后的兼砖、使用中間人私鑰加密的“服務(wù)端公鑰”奸远,在受信任的證書中查找可以用于解密的公鑰,因為之前用戶已經(jīng)信任了這個根證書讽挟,因此此公鑰可以順利被解密懒叛。

    3.客戶端隨機生成一個對稱加密(如AES)的key(密鑰),并通過“服務(wù)器提供的RSA公鑰”(已被篡改為中間人的公鑰)耽梅,對這個key進(jìn)行加密薛窥,將加密后的對稱加密key發(fā)送給服務(wù)端。

    4.中間人獲取到這個已被公鑰加密的對稱加密的key,因此加密這個對稱加密密鑰的公鑰诅迷,是自己的公鑰佩番,因此可以通過與之配對的私鑰解密,成功獲取對稱加密密鑰明文罢杉。

    5.中間人通過服務(wù)端的公鑰趟畏,對這個對稱加密密鑰進(jìn)行加密,并發(fā)送給服務(wù)端滩租,服務(wù)端通過私鑰對這個對稱加密密鑰解密赋秀,獲取對稱加密密鑰明文,服務(wù)端與客戶端之間的通訊使用這個對稱加密進(jìn)行律想,但是實際上猎莲,這個對稱加密key已被中間人成功解密,二者通訊信息一覽無遺技即,中間人可以輕松攔截和篡改https請求內(nèi)容著洼。

    信任根證書意味著信任根證書下的所有證書,此操作會極大影響用戶的信息安全而叼!

  • 【如何避免用戶抓取https請求】SSL Pinning:一些應(yīng)用將服務(wù)端的證書直接打包到App中身笤,可以在https建立連接時對比本地證書與服務(wù)器返回的證書信息,若不匹配葵陵,則立即終止https連接展鸡。但是由于是在客戶端判斷證書一致性,因此可以通過hook的方式修改客戶端的判斷邏輯來繞過SSL pinning埃难。

  • 以上https請求被攔截和篡改的前提是莹弊,用戶主動在設(shè)備中安裝并信任了根證書,因此在絕大多數(shù)情況下涡尘,https可以極大保障用戶的信息安全忍弛,很多企業(yè)和機構(gòu)開始強制要求開發(fā)者使用https進(jìn)行通訊以保證用戶的信息安全。

總結(jié)

  • http是我們?nèi)粘i_發(fā)中最常接觸到的請求-響應(yīng)協(xié)議考抄,了解其大致原理可以幫助我們?yōu)橛脩籼峁└踩煽康男畔踩U舷妇巍S捎诒救四芰驼J(rèn)知所限,以上內(nèi)容紕漏之處在所難免川梅,還望大家批評指正疯兼。

A 參考 https://github.com/SmileZXLee/aboutHttp.git

B.上面已經(jīng)說到幾個關(guān)于數(shù)據(jù)請求的安全處理.

1.服務(wù)端生成一對公鑰和私鑰把公鑰交給客戶端,
當(dāng)客戶端需要進(jìn)行數(shù)據(jù)請求的時候,數(shù)據(jù)加密處理,客戶端保存的公鑰,對請求數(shù)據(jù)進(jìn)行加密傳給后臺,后臺利用私鑰對請求解密,拿出參數(shù)進(jìn)行處理后再加密返回給客戶端.客戶端對返回的數(shù)據(jù)進(jìn)行解密然后進(jìn)行界面的展示

NSString *publicKey = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0OiXHaees9Aj5h31YYGw5nfCUdS6MK0T5UrJAfIdwkUbadDOXclDVK+ftBMe+DVAn7xSORPi1cjiBBjU+lo/hmNGoDWQGgxr/LAkaJz3/A1Sv+S1d3deTc6SFN+toDQbpsx3jYOUrJM1B8olUI1a9f+DgzkF/sIKJ7V4Wh7XtlQIDAQAB";
    //私鑰
    NSString *privateKey = @"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALQ6Jcdp56z0CPmHfVhgbDmd8JR1LowrRPlSskB8h3CRRtp0M5dyUNUr5+0Ex74NUCfvFI5E+LVyOIEGNT6Wj+GY0agNZAaDGv8sCRonPf8DVK/5LV3d15NzpIU362gNBumzHeNg5SskzUHyiVQjVr1/4ODOQX+wgontXhaHte2VAgMBAAECgYAljox63sXpk70fCq4DMay74P7WYQj/KrEn56S/rXOn8I48TcTGhYr0sT6WdM2O/EU83SSCdTsCzLebo4iK72Mx/VI1alKWSfyncfXi51gZePpgVaudTG9kcI8sszRG+P7zfPptr4HxZ7X2LveJy5myImqQomESEUvDVHdZCtIIgQJBANxT7Bev+LA+jH9gSV4Uc14B5YYabpLso39t/uhTaOdVNxV2eV2UAF1PGg2R3IMwlzHcjRkDDpBiWuXaxbTKCaECQQDRaCUb7J1mPDBrEIi1Aupho16b3Sy82vzZ9WGLgMl+eMKbSy0rAdJA10CtNKL2Gq7EGNoN4CpDPPulJTmm6Cd1AkAajH5BaHHmAtN5McgFbx9rr3zRyPOT/rHA1CdIJWzZmzoU+v6q2P+mPrbb9byFjmBZoMLbxbOGkGN1mQQDweihAkEAkAJ9Mr0AaeSOr7KJMWK16Tu+vpXWRHKdXQ9Ba/y/lThbLQ0AHQl9nJXrprICOBmVgspMeypkJiV0Mdht03joWQJAaF8kDoCNkpp++6aqVbqFBYysiW83AiHgL0JA5dhQ2XzIFYZIpLOsM+Je4yw9ppQ76DqePg6pqRKjR6m9Gatn+A==";
    //測試要加密的數(shù)據(jù)
    NSString *sourceStr = @"iOS端RSA加密";
    //公鑰加密
    NSString *encryptStr = [RSA encryptString:sourceStr publicKey:publicKey];
    //私鑰解密
    NSString *decrypeStr = [RSA decryptString:encryptStr privateKey:privateKey];
    
    NSLog(@"公鑰加密私鑰解密后的數(shù)據(jù) %@",decrypeStr);
    
    //私鑰加密
    NSString *encryptStr1 = [RSA encryptString:sourceStr privateKey:privateKey];
    //公鑰解密
    NSString *decrypeStr1 = [RSA decryptString:encryptStr1 publicKey:publicKey];
    NSLog(@"私鑰加密公鑰解密后的數(shù)據(jù) %@",decrypeStr1);

2.其實第一個很多時候就可以了.對于復(fù)雜的APP,有很多接口是不用加密的.這樣就出現(xiàn)了防代理的模式:

#pragma mark - 初步方案,判斷是否設(shè)置代理贫途,如果設(shè)置了代理就視為在抓包

- (BOOL)getProxyStatus {

    NSDictionary*proxySettings =  (__bridgeNSDictionary*)(CFNetworkCopySystemProxySettings());

    NSArray *proxies = (__bridge NSArray *)(CFNetworkCopyProxiesForURL((__bridge CFURLRef _Nonnull)([NSURL URLWithString:@"http://www.baidu.com"]), (__bridge CFDictionaryRef _Nonnull)(proxySettings)));

    NSDictionary*settings = [proxiesobjectAtIndex:0];

    NSLog(@"host=%@", [settingsobjectForKey:(NSString*)kCFProxyHostNameKey]);

    NSLog(@"port=%@", [settingsobjectForKey:(NSString*)kCFProxyPortNumberKey]);

    NSLog(@"type=%@", [settingsobjectForKey:(NSString*)kCFProxyTypeKey]);

    if([[settingsobjectForKey:(NSString*)kCFProxyTypeKey]isEqualToString:@"kCFProxyTypeNone"]){

        //沒有設(shè)置代理

        returnNO;

    }else{

        //設(shè)置代理了

        returnYES;

    }

}

這里用的CFNetwork.framework框架,進(jìn)行代理的獲取.
這種接口的處理對于用戶開VPN的情況下很多時候是有錯誤的效果.他其實沒有代理想抓你包的意思.但是開的VPN會被認(rèn)為是代理了,導(dǎo)致無法使用APP.

3.SSL Pinning

通過對服務(wù)端生成的.cer證書進(jìn)行域名校驗,服務(wù)器通過.crt證書導(dǎo)出.cer放到客戶端進(jìn)行處理.
NSURLSession處理

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {

    //得到遠(yuǎn)程證書
    SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
    SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
    //設(shè)置ssl政策來檢測主域名
    NSMutableArray *policies = [NSMutableArray array];
    [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)challenge.protectionSpace.host)];
    //驗證服務(wù)器證書
    SecTrustResultType result;
    SecTrustEvaluate(serverTrust, &result);
    BOOL certificateIsValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
    //得到本地和遠(yuǎn)程證書data
    NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
    
    BOOL allChrls = NO;
    allChrls = DebugNet;
    if (allChrls) {
        NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
        completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
    }else{
        NSString *pathToCer = [[NSBundle mainBundle] pathForResource:@"xiaoqi" ofType:@"cer"];
        NSData *localCertificate = [NSData dataWithContentsOfFile:pathToCer];    //檢查
        if ([remoteCertificateData isEqualToData:localCertificate] && certificateIsValid) {
            self.allowTask = YES;
            NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
        }else {
            self.allowTask = NO;
            [_dataTask cancel];
            [_downloadTask cancel];
            [_uploadTask cancel];
            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,NULL);
        }
    }

    
}


或者是AF里面自定義

// 自定義安全策略
+ (AFSecurityPolicy *)customSecurityPolicy {
    
    // 獲取證書
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"xiaoqi" ofType:@"cer"];
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    NSSet *pinnedCertificates = [[NSSet alloc] initWithObjects:certData, nil];

    /*
     安全模式
     AFSSLPinningModeNone:完全信任服務(wù)器證書吧彪;
     AFSSLPinningModePublicKey:只比對服務(wù)器證書和本地證書的Public Key是否一致,如果一致則信任服務(wù)器證書丢早;
     AFSSLPinningModeCertificate:比對服務(wù)器證書和本地證書的所有內(nèi)容姨裸,完全一致則信任服務(wù)器證書
     */
    AFSecurityPolicy *securityPolicy =
    [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey
                     withPinnedCertificates:pinnedCertificates];
    
    // allowInvalidCertificates 是否允許無效證書(也就是自建的證書)秧倾,默認(rèn)為NO
    // 如果是需要驗證自建證書,需要設(shè)置為YES
    securityPolicy.allowInvalidCertificates = YES;
    
    /*
    validatesDomainName 是否需要驗證域名傀缩,默認(rèn)為YES那先;
    假如證書的域名與你請求的域名不一致,需把該項設(shè)置為NO赡艰;
    如設(shè)成NO的話售淡,即服務(wù)器使用其他可信任機構(gòu)頒發(fā)的證書,也可以建立連接慷垮,這個非常危險勋又,建議打開。
    置為NO换帜,主要用于這種情況:客戶端請求的是子域名,而證書上的是另外一個域名鹤啡。
    因為SSL證書上的域名是獨立的惯驼,假如證書上注冊的域名是www.google.com,那么mail.google.com是無法驗證通過的递瑰;
    當(dāng)然祟牲,有錢可以注冊通配符的域名*.google.com,但這個還是比較貴的抖部。
    如置為NO说贝,建議自己添加對應(yīng)域名的校驗邏輯。
     */
    securityPolicy.validatesDomainName = YES;
    
    return securityPolicy;
}

證書會失效,證書由于是服務(wù)端生成的根據(jù)域名來的所以一般最長的是一年的證書.所以不能忘了換,不然可能會對接口請求產(chǎn)生問題.
那么還有沒有不用證書來校驗的方式呢?還能防止抓包呢?

蘋果官方文檔

CFNetWork

This property controls which proxy tasks within sessions based on this configuration use when connecting to remote hosts.
The default value is NULL, which means that tasks use the default system settings.

這個屬性可以設(shè)置網(wǎng)絡(luò)代理慎颗,默認(rèn)值是 NULL乡恕,使用系統(tǒng)的代理設(shè)置。
configuration.connectionProxyDictionary = @{};

#import "NSURLSession+SafeHttpProxy.h"
#import "SafeURLProtocol.h"
#import <objc/runtime.h>
static BOOL isDisableHttpProxy = YES;
@implementation NSURLSession (SafeHttpProxy)
+(void)load{
    [super load];
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [NSURLProtocol registerClass:[SafeURLProtocol class]];
        Class class = [NSURLSession class];
        [self swizzingMethodWithClass:class orgSel:NSSelectorFromString(@"sessionWithConfiguration:") swiSel:NSSelectorFromString(@"Safe_sessionWithConfiguration:")];
        [self swizzingMethodWithClass:class orgSel:NSSelectorFromString(@"sessionWithConfiguration:delegate:delegateQueue:") swiSel:NSSelectorFromString(@"Safe_sessionWithConfiguration:delegate:delegateQueue:")];
    });
}
+(void)disableHttpProxy{
    isDisableHttpProxy = YES;
}
+(void)enableHttpProxy{
    isDisableHttpProxy = NO;
}
+(NSURLSession *)Safe_sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
                                    delegate:(nullable id<NSURLSessionDelegate>)delegate
                               delegateQueue:(nullable NSOperationQueue *)queue{
    if (!configuration){
        configuration = [[NSURLSessionConfiguration alloc] init];
    }
    if(isDisableHttpProxy){
        configuration.connectionProxyDictionary = @{};
    }
    return [self Safe_sessionWithConfiguration:configuration delegate:delegate delegateQueue:queue];
}

+(NSURLSession *)Safe_sessionWithConfiguration:(NSURLSessionConfiguration *)configuration{
    if (configuration && isDisableHttpProxy){
        configuration.connectionProxyDictionary = @{};
    }
    return [self Safe_sessionWithConfiguration:configuration];
}

+(void)swizzingMethodWithClass:(Class)cls orgSel:(SEL) orgSel swiSel:(SEL) swiSel{
    Method orgMethod = class_getClassMethod(cls, orgSel);
    Method swiMethod = class_getClassMethod(cls, swiSel);
    method_exchangeImplementations(orgMethod, swiMethod);
}

@end

https://github.com/frankKiwi/FNKSafaNet.git

以上四個方案,建議是第一個加密 和 第四個結(jié)合處理.第四個對于H5頁面的網(wǎng)絡(luò)請求還是可以抓到的.

做個記錄兩年后可能就忘了.

IOS七層協(xié)議:
從下到上:
a.物理層:傳輸?shù)氖潜忍亓鞲┪W(wǎng)卡位于這層傲宜。
b.數(shù)據(jù)鏈路層:本層傳輸?shù)氖菐槐緦又饕x了如何格式化數(shù)據(jù)夫啊,錯誤檢測函卒。交換機位于本層
c.網(wǎng)絡(luò)層:本層傳輸?shù)氖菙?shù)據(jù)包,路由器位于本層撇眯。本層協(xié)議是IP協(xié)議(Internet Protocol Address)报嵌,主要功能是路由選擇最短路徑,將數(shù)據(jù)包從發(fā)送端路由到接收端
d.傳輸層:協(xié)議有TCP(傳輸控制協(xié)議)/UDP(用戶數(shù)據(jù)報協(xié)議)熊榛;主要是控制重傳锚国、數(shù)據(jù)分割之類的,主要是解決數(shù)據(jù)之間的傳輸玄坦,和傳輸質(zhì)量跷叉。是IOS最核心的一層,其中TCP協(xié)議是最重要的協(xié)議
e.會話層:不同機器之間建立會話
f.表示層:解決不同系統(tǒng)之間的語法問題
g.應(yīng)用層:應(yīng)用網(wǎng)絡(luò)中發(fā)送數(shù)據(jù):需要注意Http協(xié)議(超文本傳輸協(xié)議),Https(超文本傳輸安全協(xié)議)

TCP/IP四層模型
與IOS七層模型相同云挟,從下往上依次為:
a.鏈路層(物理層+數(shù)據(jù)鏈路層)梆砸,
b.網(wǎng)絡(luò)層(IP),
c.傳輸層(TCP)园欣,
d.應(yīng)用層(應(yīng)用層+表示層+會話層)(HTTP)帖世。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市沸枯,隨后出現(xiàn)的幾起案子日矫,更是在濱河造成了極大的恐慌,老刑警劉巖绑榴,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哪轿,死亡現(xiàn)場離奇詭異,居然都是意外死亡翔怎,警方通過查閱死者的電腦和手機窃诉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赤套,“玉大人飘痛,你說我怎么就攤上這事∪菸眨” “怎么了宣脉?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長剔氏。 經(jīng)常有香客問我塑猖,道長,這世上最難降的妖魔是什么谈跛? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任萌庆,我火速辦了婚禮,結(jié)果婚禮上币旧,老公的妹妹穿的比我還像新娘践险。我一直安慰自己,他們只是感情好吹菱,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布巍虫。 她就那樣靜靜地躺著,像睡著了一般鳍刷。 火紅的嫁衣襯著肌膚如雪占遥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天输瓜,我揣著相機與錄音瓦胎,去河邊找鬼芬萍。 笑死,一個胖子當(dāng)著我的面吹牛搔啊,可吹牛的內(nèi)容都是我干的柬祠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼负芋,長吁一口氣:“原來是場噩夢啊……” “哼漫蛔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起旧蛾,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤莽龟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后锨天,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毯盈,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年病袄,在試婚紗的時候發(fā)現(xiàn)自己被綠了搂赋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡陪拘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纤壁,到底是詐尸還是另有隱情左刽,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布酌媒,位于F島的核電站欠痴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏秒咨。R本人自食惡果不足惜喇辽,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雨席。 院中可真熱鬧菩咨,春花似錦、人聲如沸陡厘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糙置。三九已至云茸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谤饭,已是汗流浹背标捺。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工懊纳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人亡容。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓嗤疯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親萍倡。 傳聞我的和親對象是個殘疾皇子身弊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

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

  • 網(wǎng)絡(luò)安全原則 安全的原則 1)在網(wǎng)絡(luò)上不允許傳輸用戶隱私數(shù)據(jù)的明文。2)在本地不允許保存用戶隱私數(shù)據(jù)的明文列敲。 請求...
    DB001閱讀 1,200評論 0 9
  • 背景 ? 隨著移動互聯(lián)網(wǎng)的普及阱佛,被越來越多的心懷不軌的人覬覦,也越來越多的安全問題暴露了出來戴而。開發(fā)者開發(fā)出來的應(yīng)用...
    陵無山閱讀 3,031評論 1 13
  • 背景 我們知道泄鹏,http 通信存在以下問題: 通信使用明文可能會被竊聽 不驗證通信方的身份可能遭遇偽裝 無法證明報...
    廢柴程序員閱讀 3,496評論 0 41
  • 表情是什么,我認(rèn)為表情就是表現(xiàn)出來的情緒秧耗。表情可以傳達(dá)很多信息备籽。高興了當(dāng)然就笑了,難過就哭了分井。兩者是相互影響密不可...
    Persistenc_6aea閱讀 124,908評論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險厭惡者车猬,不喜歡去冒險,但是人生放棄了冒險尺锚,也就放棄了無數(shù)的可能珠闰。 ...
    yichen大刀閱讀 6,046評論 0 4