目錄
回到頂部
引言
HTTP應(yīng)用層的抓包已經(jīng)成為日常工作測(cè)試與調(diào)試中的重要一環(huán),最近接觸新項(xiàng)目突然之間發(fā)現(xiàn)之前的抓包手段都不好使了,頓時(shí)模塊與模塊之間的前端與服務(wù)之間的交互都變成了不可見,整個(gè)人都好像被蒙住了眼睛。
其實(shí)自己也很早就發(fā)現(xiàn)平時(shí)使用的支付寶等APP使用Fiddler 或 Charles這類代理抓包軟件默認(rèn)情況下就無法抓取請(qǐng)求的,但使用Wireshark這類網(wǎng)卡抓包軟件可以看到這些APP的流量,而已這些流量也表明這些APP使用的主要應(yīng)用層協(xié)議仍然是HTTP(https),不過我們的代理抓包工具卻失效了。如今終于在實(shí)際工作中遇到了,也不得不解決了,畢竟眼前有東西擋住會(huì)讓我渾身不適。
回到頂部
代理抓包原理
為了弄明白為什么Fiddler 或 Charles對(duì)這些APP無效,我們有必要先了解代理抓包我原理(當(dāng)然您不想了解也是完全可以的,直接看后面的
實(shí)際操作就可以完成,原理分析什么的可以有興趣隨時(shí)回來看)
Fiddler 或 Charles 這類使用的代理的抓包軟件與Wireshark是完全不同的(Wireshark 使用的網(wǎng)卡數(shù)據(jù)復(fù)制,只要是經(jīng)過指定網(wǎng)卡都會(huì)被抓?。?,其只能對(duì)使用代理的應(yīng)用層網(wǎng)絡(luò)協(xié)議生效,比如常見的HTTP(https),Websocket 。
這里以HTTP為例簡(jiǎn)單說明下
客戶端需要完成一次HTTP請(qǐng)求,通常需要先找到服務(wù)器,客戶端會(huì)根據(jù)http請(qǐng)求中url的主機(jī)名(實(shí)際會(huì)使用host中的主角名)及其端口與目標(biāo)主機(jī)建立tcp連接,建立連接后會(huì)將http報(bào)文發(fā)送給目標(biāo)服務(wù)器 (更多細(xì)節(jié)請(qǐng)參考
https://tools.ietf.org/html/rfc7232)
接下來我來看下HTTP代理是如何運(yùn)作的,我們啟動(dòng)Fiddler 或 Charles就是啟動(dòng)了一個(gè)HTTP代理服務(wù)器,這類工具會(huì)通知操作系統(tǒng),“現(xiàn)在我在系統(tǒng)上創(chuàng)建了一個(gè)HTTP代理,IP為XXXXXX端口為XX。如果您使用的是linux您可以手動(dòng)通知操作系統(tǒng)(export http_proxy=ip:port export https_proxy=$http_proxy),如果您使用的是手機(jī)等移動(dòng)設(shè)備您可以在當(dāng)前wifi設(shè)置處告訴系統(tǒng)你要使用http代理。 現(xiàn)在我們已經(jīng)告訴系統(tǒng)我們想要使用代理,這個(gè)時(shí)候運(yùn)行在系統(tǒng)上的http客戶端再去發(fā)送請(qǐng)求的時(shí)候,他就不會(huì)再去進(jìn)行DNS解析,去連接目標(biāo)服務(wù)器,而是直接連接系統(tǒng)告訴他代理所在的地址(代理的ip及端口,注意無論是http或https或其他支持代理的協(xié)議都會(huì)連接同一個(gè)端口)。然后代理服務(wù)器會(huì)與客戶端建立連接,再然后代理服務(wù)器根據(jù)請(qǐng)求信息再去連接真正的服務(wù)器。
這里還有個(gè)細(xì)節(jié)正常在沒有代理的情況下客戶端向服務(wù)器發(fā)送的請(qǐng)求行里只包含部分URI(實(shí)際上是沒有方案,主機(jī)名及端口的)
如上圖如果在沒有代理的情況下,對(duì)www.baidu.com/index.html的請(qǐng)求的請(qǐng)求行實(shí)際上是GET /index.html HTTP/1.1 其實(shí)并不是我們常見的完整uri。因?yàn)樵谠嫉腍TTP設(shè)計(jì)中沒有考慮中間服務(wù)器(即代理)的情況,客戶端在發(fā)送報(bào)文前已經(jīng)知道服務(wù)器的地址并與之建立了連接,沒有必要再發(fā)送方案,主機(jī)名及端口。不過代理出現(xiàn)后這種做法就會(huì)有問題了,客戶端連接了代理服務(wù)器,而代理服務(wù)器卻沒有辦法連接正確的服務(wù)器。因此客戶端發(fā)送給代理的請(qǐng)求其實(shí)稍有不同,客戶端會(huì)在請(qǐng)求行里使用完整的uri,這樣代理服務(wù)器才能解析真實(shí)的服務(wù)器的地址。
現(xiàn)在我們的請(qǐng)求實(shí)際上都是通過代理服務(wù)器(Fiddler 或 Charles)發(fā)送出去的,所以代理抓包軟件不僅知道http請(qǐng)求及響應(yīng)的所有報(bào)文,甚至還可以隨時(shí)修改請(qǐng)求及響應(yīng)。
回到頂部
部分應(yīng)用不能抓包的原因
可以看到代理抓包的關(guān)鍵就是需要HTTP客戶端按照要求去連接代理服務(wù)器,一般情況下我們已經(jīng)在系統(tǒng)層面上設(shè)置了代理,通常http客戶端都是按要求去實(shí)現(xiàn)的,在進(jìn)行http請(qǐng)求前會(huì)先檢查系統(tǒng)代理,如果有設(shè)置代理,客戶端會(huì)直接使用完整uri去連接代理服務(wù)器。不同的平臺(tái)通常會(huì)實(shí)現(xiàn)自己的的http客戶端的,雖然他們都按照協(xié)議要求實(shí)現(xiàn)了代理功能,但是并不一定在默認(rèn)情況下會(huì)直接使用系統(tǒng)代理。
在現(xiàn)實(shí)中這種況下這種情況還不少,筆者當(dāng)前項(xiàng)目使用到的Flutter就是這種情況,默認(rèn)Flutter不會(huì)主動(dòng)使用系統(tǒng)代理,需要單獨(dú)設(shè)置。(當(dāng)然個(gè)人認(rèn)為這種策略也是有理由,雖然給測(cè)試及調(diào)試帶來了不便不過也在一程度上提高了些許數(shù)據(jù)安全)
正是因?yàn)镠TTP客戶端沒有使用我們?cè)O(shè)置的系統(tǒng)代理,他們自然也不會(huì)連接Fiddler 或 Charles創(chuàng)建的代理服務(wù)器,最終導(dǎo)致我們無法獲取任何請(qǐng)求。
回到頂部
解決方案
不過既然我們已經(jīng)知道了Fiddler 和 Charles不能抓包的具體原因,前面也提到了代理抓包的原理,那我們就總有辦法解決。
前面說到了我們APP使用的HTTP客戶端沒有連接到代理服務(wù)器,導(dǎo)致我們的代理抓包軟件無法正常抓包,那我們只要想辦法讓客戶端重新連接到代理服務(wù)器就好了(當(dāng)然這一切都是以不修改客戶端軟件APP為前提的)
方法1:控制DNS解析,通過修改dns的方式讓客戶端以為我們的代理服務(wù)器就是目標(biāo)服務(wù)器。
優(yōu)勢(shì):操作方便,通過修改設(shè)備的hosts可以十分方便的首先
劣勢(shì):需要為每個(gè)需要操作的域名提前添加host
在手機(jī)等手持設(shè)備上難以修改hosts(即對(duì)移動(dòng)APP這類應(yīng)用很難實(shí)現(xiàn))
方法2:在網(wǎng)絡(luò)設(shè)備上直接做流量轉(zhuǎn)發(fā),將指定終端設(shè)備上發(fā)往80及443端口的數(shù)據(jù)直接轉(zhuǎn)發(fā)到代理服務(wù)器的 目標(biāo)端口上
優(yōu)勢(shì):可以針對(duì)連接到網(wǎng)絡(luò)設(shè)備上的終端設(shè)備進(jìn)行分別配置,而手機(jī)等終端設(shè)備不需要進(jìn)行任何設(shè)備
劣勢(shì):需要單獨(dú)的硬件設(shè)備
方法3:使用VPN將終端設(shè)備的流量轉(zhuǎn)發(fā)到代理服務(wù)器
優(yōu)勢(shì):使用VPN軟件不用添加其他測(cè)試。
劣勢(shì):終端上的VPN默認(rèn)會(huì)直接對(duì)所有流量進(jìn)行轉(zhuǎn)發(fā),要進(jìn)行合理的配置可能需要額外的學(xué)習(xí)成本
回到頂部
實(shí)際操作步驟(Android)
筆者這里直接使用上面提到第3種方法(方法1在對(duì)于手機(jī)APP很難操作,方法2可能需要其他設(shè)備所以這里不使用),因?yàn)槲覀兊臏y(cè)試對(duì)象是手機(jī)移動(dòng)APP,所以我們首先要在手機(jī)上安裝一個(gè)VPN,這里使用一個(gè)十分方便的VPN軟件drony (介紹在這里
https://github.com/SuppSandroB/sandrop/wiki/Drony-FAQ),drony會(huì)在你的手機(jī)上創(chuàng)建一個(gè)VPN,將手機(jī)上的所有流量都重定向到drony自身(不是流向vpn服務(wù)器) ,這樣drony就可以管理所有手機(jī)上的網(wǎng)絡(luò)流量,甚至可以對(duì)手機(jī)上不同APP的流量進(jìn)行單獨(dú)配置。
1:安裝drony (這里手機(jī)使用的Android設(shè)備)
您可以在網(wǎng)絡(luò)上搜索drony選擇自己想要的版本進(jìn)行安裝,或者在這里下載(
https://files.cnblogs.com/files/lulianqi/Drony_102.apk),安裝完成后打開軟件如下圖
2:開啟代理抓包軟件(這里代理抓包軟件使用的是Fiddler)
Fiddler的使用這里不再介紹,需要打開遠(yuǎn)程代理,并在手機(jī)中安裝Fiddler根證書
這里筆者開啟的遠(yuǎn)程代理的地址是192.168.2.244:8888
關(guān)于證書安裝有些細(xì)節(jié),F(xiàn)iddler默認(rèn)的根證書是cer格式,部分手機(jī)可能只能識(shí)別pem格式證書
直接使用openssl 轉(zhuǎn)一下就行了 (openssl x509 -inform der -in FiddlerRoot.cer -out FiddlerRoot.pem)
openssl 在中 windows/mac 一般都安裝有,命令直接使用就行了,使用生成的FiddlerRoot.pem安裝到手機(jī)上就行了(Charles默認(rèn)就是pem證書)
3:配置drony轉(zhuǎn)發(fā)

打開Drony(處于OFF狀態(tài)),滑動(dòng)到SETING頁(yè),點(diǎn)擊選擇Networks Wi-Fi 進(jìn)入配置
在網(wǎng)絡(luò)列表中選擇點(diǎn)擊當(dāng)前手機(jī)wifi連接的網(wǎng)絡(luò) (需要確保該網(wǎng)絡(luò)與Fiddler代理服務(wù)器網(wǎng)絡(luò)是聯(lián)通的)

配置要為當(dāng)前網(wǎng)絡(luò)使用的代理入口(這里直接填寫fiddler代理地址就可以),選擇代理模式為手動(dòng)(Manual)
注意Proxy type代理方式要選擇 Plain http proxy
Filter default value 選擇 Direct all ,然后點(diǎn)擊下面的Rule設(shè)置應(yīng)用規(guī)則
默認(rèn)您的規(guī)則里應(yīng)該是空的,這里直接點(diǎn)擊上面的加號(hào)添加一個(gè)規(guī)則(符合規(guī)則要求的才會(huì)被轉(zhuǎn)發(fā))
說明一下后面的操作會(huì)以咸魚或支付寶做演示說明,不過筆者當(dāng)前測(cè)試項(xiàng)目并不是咸魚或支付寶,也不是其公司的員工,選擇這2個(gè)APP做演示是因?yàn)檫@些APP比較常用,且無法抓包的原因與筆者當(dāng)前項(xiàng)目APP是類似的。
在Network id處 選擇當(dāng)前wifi的SSID
Action 選擇 Local proxy chain
Application 選擇需要強(qiáng)制代理的APP
Hostname 及 Port 不填 表示所有的都會(huì)被強(qiáng)制代理,因?yàn)锳PP可能會(huì)使用其他的網(wǎng)絡(luò)協(xié)議不一定都是http,可能不希望把所有流量都引流到http代理服務(wù)器,這個(gè)時(shí)候就會(huì)使用這個(gè)配置指定ip及端口才轉(zhuǎn)發(fā)
完成后保存即可,然后返回到SETTING主頁(yè),滑動(dòng)到LOG頁(yè),點(diǎn)擊下面按鈕,使其處于ON的狀態(tài)(表示啟用)
這個(gè)時(shí)候啟動(dòng)支付寶或咸魚,我們就可以在Fiddler上看到正常的流量。不過如果你的運(yùn)氣與筆者一樣可能只能看到這些Tunnel to (TLS管道建立),如果您使用的是Charles在列表里看到的可能是一個(gè)個(gè)紅叉。
當(dāng)然筆者Fiddler根證書是安裝成功的,F(xiàn)iddler配置也是正確的(手機(jī)上的Chrome https抓包都是正常的)
既然流量已經(jīng)到Fiddler了,Drony的工作算是完美完成了,之所部分APP以不能解密https報(bào)文,還是我們自己證書的問題。首先先簡(jiǎn)單描述下證書校驗(yàn)的過程(如果不想看這些過程可以直接看后面
操作步驟)
回到頂部
證書校驗(yàn)原理
無論Fiddler 或 Charles都使用中間人攻擊的方式替換tls鏈路證書,解密報(bào)文然后再加密發(fā)送給真實(shí)服務(wù)器。
您可以參看
HTTPS中間人攻擊實(shí)踐(原理·實(shí)踐)了解中間人攻擊的細(xì)節(jié)
存在代理的情況下客戶端首先連接的是代理服務(wù)器(即是圖中的攻擊者),實(shí)際client是直接與Proxy建立的TLS通道,所以代理當(dāng)然TLS通道的傳輸密鑰然后解密報(bào)文。
不過由于證書的存在,client會(huì)校驗(yàn)證書的合法性,然后決定是否連接服務(wù)器。我們使用Fiddler或Charles抓取https前在設(shè)備中安裝根證書正是為了通過client的證書校驗(yàn)。
在瀏覽器中任意找一個(gè)https的網(wǎng)頁(yè),查看其證書信息。
從這里面我們能看到證書包含以下內(nèi)容:
(1) Validity也即有效期,有效期包含生效時(shí)間和失效時(shí)間,是一個(gè)時(shí)間區(qū)間;
(2) 公鑰信息Subject Public Key Info,包括公鑰的加密算法和公鑰內(nèi)容;
(3) 指紋信息,指紋用于驗(yàn)證證書的完整性,也是證書校驗(yàn)的關(guān)鍵,他保證書沒有被修改過。 其原理就是在發(fā)布證書時(shí),發(fā)布者根據(jù)指紋算法(此處證書使用了SHA-1和SHA-256算法 有多個(gè)指紋是為了兼容老的客戶端)計(jì)算整個(gè)證書的hash指紋【證書內(nèi)容hash值使用CA私鑰加密就是指紋】并和證書放在一起,client在打開證書時(shí),自己也根據(jù)指紋算法計(jì)算一下證書的hash值,同時(shí)使用自己信任的根證書的公鑰解密hash指紋計(jì)算出原始hash,如果hash值不一致,則表明證書內(nèi)容被篡改過;
(4) 證書的簽名Certificate Signature Value和Certificate Signature Algorithm,對(duì)證書簽名所使用的Hash算法和Hash值;
(5) 簽發(fā)該證書的CA機(jī)構(gòu)Issuer;
(6) 該證書是簽發(fā)給哪個(gè)組織/公司信息Subject;
(7) 證書版本Version、證書序列號(hào)Serial Number以及Extensions擴(kuò)展信息等。
上圖即是證書指紋校驗(yàn)的過程,可能看到Client校驗(yàn)證書的核心其實(shí)是CA公鑰解密原始指紋,CA公鑰從哪里來,為了確保安全設(shè)備系統(tǒng)會(huì)有一批自己信任的CA公鑰列表(根證書)。這些CA公鑰對(duì)應(yīng)的一般是權(quán)威機(jī)構(gòu)或組織,然后由這些權(quán)威機(jī)構(gòu)頒發(fā)證書時(shí)會(huì)使用他們自己的私鑰去簽名(為證書生成指紋)。這樣就確保了只有權(quán)威機(jī)構(gòu)頒發(fā)給各個(gè)網(wǎng)站的證書才會(huì)被客戶端校驗(yàn)通過。
Filddler沒有這些證書里公鑰對(duì)應(yīng)的私鑰(CA只會(huì)把為完整頒發(fā)的證書對(duì)應(yīng)的私鑰給網(wǎng)站的所有者),所以沒有辦法與客戶端完成TLS握手。Filddler為了完成握手只能自己為不同的站點(diǎn)生成證書,
不過自己的生成的證書肯定是用自己的私鑰簽名的,客戶端在自己信任的CA公鑰列表找不到對(duì)應(yīng)根證書,肯定是不能通過證書校驗(yàn)的。所以Filddler要求我們安裝他的根證書到設(shè)備,這樣自己簽發(fā)的證書就可以通過證書校驗(yàn),自己就能解密https報(bào)文了。
回到頂部
不能解密的原因
其實(shí)通過上面的描述也很明白了不能正常建立連接解密https報(bào)文的原因就是證書校驗(yàn)失敗,我們的根證書安裝不夠完全。
從Android7.0以后,系統(tǒng)允許每個(gè)應(yīng)用可以定義自己的
可信CA集。有部分應(yīng)用默認(rèn)只會(huì)信任系統(tǒng)預(yù)裝的CA證書,而不會(huì)信任用戶安裝的CA證書(或者說是應(yīng)用使用的開發(fā)框架默認(rèn)只信任系統(tǒng)證書,因?yàn)殚_發(fā)者通常不關(guān)心這些配置,也不會(huì)去更改他)。而在Android中用戶安裝的證書都是用戶證書,所以無論是Filddler還是Charles我們都只是把他們的根證書安裝到了用戶證書,這些應(yīng)用并不使用他們,所以我們的安裝的證書是無效的。
回到頂部
解決方法及操作方法
既然又知道了原因,那就總還是有辦法去解決的。我們只要把代理軟件的根證書安裝成系統(tǒng)證書就可以了。
實(shí)際上將證書安裝到系統(tǒng)區(qū)操作還是相對(duì)簡(jiǎn)單的,將證書用指定的名稱放到指定的位置(/system/etc/security/cacerts/)就可以了
先將我們的根證書名稱改為<Certificate_Hash>.<Number>
Certificate_Hash表示證書文件的hash值,Number是為了防止證書文件的hash值一致而增加的后綴(用0就行了)
下載自己的根證書FiddlerRoot.cer,使用openssl x509 -subject_hash_old -in <Certificate_File> 計(jì)算證書hash ,根據(jù)hash將證書重命名為 269953fb.0 (269953fb是筆者證書的hash,大家的肯定不一樣)
然后將269953fb.0文件復(fù)制到/system/etc/security/cacerts/
完成后我們就可以看到代理軟件的證書出現(xiàn)在系統(tǒng)區(qū)了。
這里還有一點(diǎn)需要單獨(dú)說明,/system/etc/security/cacerts/目錄的寫權(quán)限,需要手機(jī)root權(quán)限。
也就是說復(fù)制證書到該目錄需要您root自己的設(shè)備。
關(guān)于Android手機(jī)的root,通常手機(jī)廠家都會(huì)有自己官方的教程,建議大家按官方的操作進(jìn)行root
以小米手機(jī)為例 (
http://www.miui.com/thread-12281379-1-1.html)
當(dāng)前小米手機(jī)的root需要手機(jī)綁定小米賬號(hào)7天以上才能解鎖,解鎖后刷入開發(fā)版即可完成root
需要注意的是不是所有小米的手機(jī)都有對(duì)應(yīng)的開發(fā)版的,所以購(gòu)買測(cè)試設(shè)備時(shí)留意下。(
http://www.miui.com/download.html 這里可以看下自己的手機(jī)有沒有開發(fā)版可以使用)
效果
現(xiàn)在證書也被安裝到了系統(tǒng)區(qū),再回到Fiddler看下效果
再次打開閑魚我們已經(jīng)可以看到完整的https請(qǐng)求了。
下面我們找個(gè)請(qǐng)求修改一下請(qǐng)求返回?cái)?shù)據(jù)看下效果
借助Fiddler插件FreeHttp修改這個(gè)請(qǐng)求的返回?cái)?shù)據(jù)將二手手機(jī)修改為二手馬總并將圖片也替換掉
配置如下圖

(FreeHttp的具體使用請(qǐng)參考
借助FreeHttp任意篡改http報(bào)文 (使用·實(shí)現(xiàn)))
再次打開閑魚,可以看到經(jīng)過代理的數(shù)據(jù)已經(jīng)被篡改了(注意測(cè)試時(shí)清除咸魚的緩存及應(yīng)用數(shù)據(jù),以保證每次打開APP都會(huì)請(qǐng)求firstdata)
經(jīng)過上面到配置,這些APP的HTTP流量我們就可以通過代理抓包軟件獲取,https流量也可能正常解碼。
回到頂部
IOS設(shè)備操作步驟(IOS)
ios(iphone)同樣使用上面提到第3種方法(原理與android是一致的),同樣需要使用到VPN,在ios也有許多與drony功能類似的軟件,大家可以自己選擇自己喜歡的使用,筆者這里使用的是Shadowrocket

如上圖您可以直接在App Store找到這些軟件(受限于大陸相關(guān)規(guī)定,您的App Store的區(qū)域如果在國(guó)內(nèi)可能無法搜索到這些軟件,您需要使用美區(qū)的賬號(hào))
為了完成流量重新定向,Shadowrocket與drony一樣會(huì)先在設(shè)備上創(chuàng)建本地VPN服務(wù),再使用您設(shè)置的規(guī)則處理流量。
不過Shadowrocket的使用會(huì)更加方便,直接打開軟件如下圖配置即可

- 選擇全局路由為「代理」
- 添加服務(wù)節(jié)點(diǎn)(類型選擇HTTP及HTTPS ,服務(wù)器地址及端口為您代理抓包工具的地址與端口)
- 設(shè)置狀態(tài)為啟用 (IOS會(huì)同時(shí)自動(dòng)創(chuàng)建VPN)
現(xiàn)在直接打開iphone上的任意APP(不用再再wifi上重復(fù)設(shè)置代理) ,既可以在代理抓包工具上看到流量了,同樣不能解析HTTPS的流量,不過IOS并沒有像新版的android一樣可以讓APP拒絕用戶手動(dòng)信任的用戶根證書,所以IOS證書安裝IOS也比android任意的多,并沒有這么多額外的操作,按正常證書安裝流程操作即可。證書安裝完成后即可查看HTTPS流量
