為了搶口罩,我竟然把 https 的原理整明白了
疫情當下,口罩難搶啊,沒有口罩的我不能出門。在 52 破解上看到了一個口罩查詢余量的軟件。
軟件類似這樣子:
我用這軟件蹲點搶來好久,也沒搶到。于是我尋思著,能不能把這個軟件的口罩消息來源給搞到。由于是一枚菜雞 web 狗,俺也不會逆向。通過 wireshark 來抓請求看看他到底是咋弄的。
看他軟件上的提示,是每隔 5s 就請求一次數(shù)據(jù)。由于 wireshark 抓包的數(shù)據(jù)是抓這個網(wǎng)卡的全部流量,分析起來比較多。打開 wireshark,抓了一會包就停了沒必要太久。不然會很多其他的流量請求。
可以看到居多數(shù)給 27.124.36.8 這個 IP 發(fā)包,我日還是 https,這可咋整。沒有密鑰咋解密呢。嗯,雖然解不開數(shù)據(jù)包,不知道他以什么樣子的參數(shù)去發(fā)送,但是我們能看到服務器的證書信息。
發(fā)現(xiàn)了一個 app.tonystark.io
僅僅是找到了服務器的地址,具體的口罩信息的請求方式,我們還是不知道。
從上面 wireshark 的流量,我們可以知道程序與服務器之間的通信是使用 https 來連接,在解密之前我們先來學一下 https 的原理吧。
一、Https 原理學習
https 與 http 相比,僅僅多了一層的 tls:
1. 為什么要加入這一層tls安全層呢?
是因為最初的 HTTP 存在下面三個問題:
- 數(shù)據(jù)在裸奔。數(shù)據(jù)以明文的方式傳播
- 無法驗證通信雙方的身份
- 無法防止數(shù)據(jù)被篡改
我們先來解決第一個問題,如何給數(shù)據(jù)加密?
- 密碼學加密方式只有對稱密碼和非對稱密碼
- 對稱密碼:加密的加密和解密使用同一密鑰。
從流程圖中得到,這種加密方式在雙方通信時候需要預先準備好密鑰。但是服務器和瀏覽器之間傳遞密鑰的過程被人監(jiān)聽,相當于明文傳輸。倘若預先把密鑰保存在本地,到需要建立連接在取出,那么瀏覽器需要預存好世界上所以的 HTTPS 網(wǎng)站的密鑰,顯然不現(xiàn)實。
非對稱密碼:公鑰加密,私鑰解密
這種加密方式, 也稱為非對稱密鑰加密,使用一對密鑰用于加密和解密,分別為公開密鑰和私有密鑰。公開密鑰所有人都可以獲得,通信發(fā)送方獲得接收方的公開密鑰之后,就可以使用公開密鑰進行加密,接收方收到通信內容后使用私有密鑰解密。因為公鑰加密,私鑰解密,即使傳輸中的公鑰被監(jiān)聽了,也解不開傳輸?shù)牧髁?。但是僅僅是客戶端到服務器這條傳輸鏈路保證了傳輸?shù)陌踩敲丛趺幢WC服務端下行到客戶端這條鏈路的安全呢?
HTTPS 采用混合的加密機制,使用公開密鑰加密用于傳輸對稱密鑰,之后使用對稱密鑰加密進行通信。
首先 Client 發(fā)起想要連接 Server,則會發(fā)送 ClientHello,這個 Hello 信息標識就是 Client 最高支持的 TLS 版本,支持的密碼套件,Session 信息以及壓縮算法。
而 Server 收到 Client 的請求后,會發(fā)送與協(xié)商確定 Client 的密碼套件,同時會發(fā)送 Server Certificate 證書信息和服務器公鑰。
Client 收到 ServerHello 后,會驗證 Server 的證書信息是否合法,如果合法,則產生隨機碼(這一步又涉及到TLS的密鑰計算,太過復雜了,大家有興趣可以自己去查閱),作為對稱密鑰加密密鑰,對隨機碼使用接收到的服務器公鑰進行加密。
大概的流程圖就是這樣子,不同的 TLS 版本流程很不一樣。
下面我用 wireshark 來抓一次 csdn 的 https 連接請求。
首先先看 ClientHello,TLS 版本信息,Session,以及支持的密碼套件
隨后的 ServerHello,不難發(fā)現(xiàn)選擇了 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 的加密方法
可以看到,ServerHello 后面還跟著一個數(shù)據(jù)包。其中有三個關鍵字:Certificate 、Certificate Status 、Server Key Exchange
Certificate 就是證書信息:
從數(shù)據(jù)包可以看出是由 www.digicert.com 簽發(fā),并且采用 sha256WithRSAEncryption 進行簽名
Certificate Status 則是證書的狀態(tài)信息,包含證書的有效期至
最后 Server Key Exchange 則是 Server 的 Public Key 了
由于協(xié)商出來的是 ECDHE 密鑰協(xié)商算法 ,所以 Server 把 ECDH 的參數(shù)和公鑰發(fā)給 Client。這里的 ECDH 曲線是 secp256r1,公鑰是 047b36092eb10...............
至此 ServerHello 結束。
由于是 ECDHE 協(xié)商算法,所以 Client 需要發(fā)送 ECC DH 公鑰,也有三個關鍵字:
Client Key Exchange 不必多說,是 Client 發(fā)送的 ECCDH 公鑰,其值是 04acb6e.....
ChangeCipherSpec 消息結構很簡單,發(fā)送這條消息是為了告訴 Server ,Client 可以使用 TLS 記錄層協(xié)議進行密碼學保護了。第一條進行密碼學保護的消息是 Finished 消息。
后面兩個數(shù)據(jù)包則是流量控制。有助于確保只傳播接受者需要使用的數(shù)據(jù)數(shù)據(jù)。之后就是新的 session 建立,Server 返回 ChangeCipherSpec 和 finish。這里還有一部分的 TLS 會話復用機制。請讀者自行查閱。
目前為止 https 整個連接已經建立起來了。
現(xiàn)在我們已經解決了Https如何給數(shù)據(jù)加密的過程。
2. 現(xiàn)在來看第二個問題:如何驗證通信雙方的身份?
在上面的 wireshark 流量分析中,我們可以看到一個 Certificate 的身影。沒錯, HTTPS 通過使用 證書 來對通信方進行認證。
數(shù)字證書認證機構(CA,Certificate Authority)是客戶端與服務器雙方都可信賴的第三方機構。服務器的運營人員向 CA 提出公開密鑰的申請,CA 在判明提出申請者的身份之后,會對已申請的公開密鑰做數(shù)字簽名,然后分配這個已簽名的公開密鑰,并將該公開密鑰放入公開密鑰證書后綁定在一起。
進行 HTTPS 通信時,服務器會把證書發(fā)送給客戶端,客戶端取得其中的公開密鑰之后,先進行驗證,如果驗證通過,就可以開始通信。
舉個例子
上圖中的步驟 1、2、3、4 并不是每次都需要這樣請求。1、2、3 步只需要在注冊新的公鑰的時候才會進行。第四步僅在第一次需要使用公鑰密碼的時候需要,之后保存到了電腦中,就不用每次都請求公鑰了。
網(wǎng)站在使用HTTPS前,需要向“CA機構”申請頒發(fā)一份數(shù)字證書,數(shù)字證書里有證書持有者、證書持有者的公鑰等信息,服務器把證書傳輸給瀏覽器,瀏覽器從證書里取公鑰就行了,證書就如身份證一樣,可以證明“該公鑰對應該網(wǎng)站”
二、那么怎么認證數(shù)據(jù)的完整性?舉個例子 :
A 向 B 匯錢 100 萬元。如果攻擊者從中攻擊,篡改這條消息,就可能變成 A 向攻擊者匯錢 1000 萬元。這里針對匯款消息。如何保證兩個問題:消息的 “完整性” 和 “認證” 。
這時候可以用到數(shù)字簽名技術,相當于現(xiàn)實生活的蓋章。數(shù)字簽名可以識別篡改、偽裝、防止抵賴。
非對稱密鑰是公鑰加密,私鑰解密。而數(shù)字簽名是公鑰解密,私鑰加密??匆粋€流程
為了防止消息被篡改和被偽造,使用數(shù)字簽名技術,服務端使用私鑰對消息的 hash 進行加密,再把 hash 和簽名發(fā)送給客戶端,隨后客戶端利用公鑰進行解密,比對傳輸?shù)?hash 是否一致。如果一致就證明消息未被篡改和偽造。
我們都知道,指紋是一個人獨一無二的東西,能通過它找他對應的唯一一個人。而消息的指紋就是密碼學中的單向散列函數(shù) (Hash)。每一個消息都有其對應的 Hash,如果消息發(fā)生了變換,其 hash 也會隨之變換。
消息的完整性,就叫消息的一致性,這個可以用消息指紋來判斷,通過對比單向散列函數(shù)的 hash 值來判斷這條消息的完整性,有沒有被篡改。
消息的認證,指的是,消息是否來自正確的發(fā)送者。如果確認匯款請求確實來自 A,就相當于對消息進行了認證,代表消息沒有被偽裝。
好了 Https 大概完成了 Http 不曾完成的三個使命。想必看完你也大概了解了 Https 是怎么實現(xiàn)它所說的安全的。
三、怎么才能夠對流量進行解密?
網(wǎng)上搜索大多都是兩種解法,一種是導入 RSA 私鑰進入 wireshark。第二種是配置 SSLKEYLOGFILE。
第一種:導入 RSA 私鑰進入 wireshark
實現(xiàn)過程:
1. 拿到百度的服務器證書
使用 fiddler 的中間人代理技術拿到含有私鑰的服務器證書。
- 打開 fiddler 并啟用 https 代理服務
- 用配置了 fiddler 代理的瀏覽器訪問百度
- 運行 “certmgr.msc”打開證書管理器
- 從 Personal/Certificates 目錄下找到 *.baidu.com 的證書,右鍵所有任務-導出
2、取出證書中的私鑰
使用 openssl 取出私鑰。
1) 將 pfx 證書轉為 pem 證書
命令行:
- openssl pkcs12 -in <pfx證書路徑> -nodes -out <輸出的pem證書路徑(.pem)>
2) 從 pem 證書中取出私鑰
命令行:
- openssl rsa -in <pem證書路徑> -out <輸出的私鑰文件路徑(.key)>
3) 點擊編輯——>首選項——>協(xié)議——>SSL(有的版本只有 TLS),導入 RSA key:
導入服務器證書:
點擊 ok 后,Wireshark 會對捕獲的報文進行解密:
這種方法僅僅對于使用 RSA 的密鑰交換有用,在知曉了 RSA 密鑰,就可以導入 wireshark 來解密流量。但是目前大多數(shù)的 HTTPS 網(wǎng)站都是采用 DH 密鑰交換。在此說明一下 RSA 和 DH 的區(qū)別。先看這個兩個的過程。
ssl_handshake_rsa:
- Client Hello,包含協(xié)議版本、客戶端 random、密碼套件列表
- Server Hello,服務器“hello”消息包含服務器隨機、服務器選擇的密碼套件和服務器的證書
- Client Key Exchange Client 驗證證書后,客戶端創(chuàng)建一個隨機的 pre-master secret。并使用公鑰加密發(fā)送 之后服務器收到加密的 pre-master secret 會使用私鑰進行解密。所以,我們知道私鑰,就可以導入 wireshark ,解出 pre-master secret 來解密流量。
ssl_handshake_diffie_hellman:
- Client Hello,包含協(xié)議版本、客戶端 random、密碼套件列表
- Server Hello,服務器“hello”消息包含服務器隨機、服務器選擇的密碼套件和服務器的證書
- Server Key Exchange 緊跟著 Server Hello,為了啟動 DH 交換,服務器會發(fā)送 Diffie-Hellman 參數(shù)和簽名
- Client Key Exchange 客戶端會驗證服務器的證書。然后會向服務器發(fā)送 DH 參數(shù)。
注:整個過程不存在密鑰的交換,客戶端服務端可以通過 DH 參數(shù)來計算 pre-master secret。
對于這種情況,由于 Premaster Secret 無需交換,中間人就算有私鑰也無法獲得 Premaster Secret 和 Master Secret。也就是說 Wireshark 無法通過配置 RSA Private Key 的方式解密「使用 ECDHE 進行密鑰交換」的加密流量。
第二種 SSLKEYLOGFILE
在系統(tǒng)環(huán)境變量加入SSLKEYLOGFILE這個變量,并選擇導出目錄
Firefox 和 Chrome 都會在系統(tǒng)環(huán)境變量存在 SSLKEYLOGFILE 文件路徑時,將每個 HTTPS 連接產生的 Premaster Secret 或 Master Secret 存下來。有了這個文件,Wireshark 就可以輕松解密 HTTPS 流量
然后打開 wireshark,ctrl+shift+P 在 Protocols 選擇 TLS 協(xié)議,并導入即可
即可解除加密
可是這兩種對我都沒用啊。這個是程序與服務器連接,弄不出來 HTTPS 連接產生的 Premaster Secret 或 Master Secret。而且每次連接的 Secret 都是隨機的啊。
下面就要說到另外一種。學安全的大家都知道,burp 在抓取 https 流量的時候,需要信任 burp 的證書。那么大家可想過,這是為何?
burp,Charles,fildder這些抓包工具,主要是利用了中間人攻擊的思想,
正常的通信只有 Client,Server。
中間人攻擊的時候,加入了一個中間方。Client 信任中間方的證書后,就會和中間方進行通信。然后中間方拿到 Client 發(fā)送的請求,就會偽裝成 Client 對服務方建立請求。監(jiān)聽雙方的通信。
所以只要 Client 信任了 burp 的證書,Client 會和 burp 建立 Https 連接。burp 收到 Client 的請求后,則會去和 Server 建立連接,偽造 Client 通信。
想必看到這里你們腦海中浮現(xiàn)一個疑問:不是說 Https 可以驗證通信雙方的身份?
是這樣子的。Https 有單端驗證和雙端驗證
圖片來源:https://www.jianshu.com/p/a2a7ddce7075
一般 Web 應用都是采用 SSL 單向認證的,原因很簡單,用戶數(shù)目廣泛,且無需在通訊層對用戶身份進行驗證,一般都在應用邏輯層來保證用戶的合法登入。但如果是企業(yè)應用對接,情況就不一樣,可能會要求對客戶端(相對而言)做身份驗證。這時就需要做 SSL 雙向認證。
- 客戶端向服務端發(fā)送SSL協(xié)議版本號、加密算法種類、隨機數(shù)等信息。
- 服務端給客戶端返回SSL協(xié)議版本號、加密算法種類、隨機數(shù)等信息,同時也返回服務器端的證書,即公鑰證書
- 客戶端使用服務端返回的信息驗證服務器的合法性,包括:證書是否過期、發(fā)型服務器證書的CA是否可靠、返回的公鑰是否能正確解開返回證書中的數(shù)字簽名、 服務器證書上的域名是否和服務器的實際域名相匹配、驗證通過后,將繼續(xù)進行通信,否則,終止通信
- 客戶端向服務端發(fā)送自己所能支持的對稱加密方案,供服務器端進行選擇
- 服務器端在客戶端提供的加密方案中選擇加密程度最高的加密方式。
- 服務器將選擇好的加密方案通過明文方式返回給客戶端
- 客戶端接收到服務端返回的加密方式后,使用該加密方式生成產生隨機碼,用作通信過程中對稱加密的密鑰,使用服務端返回的公鑰進行加密,將加密后的隨機碼發(fā)送至服務器
- 服務器收到客戶端返回的加密信息后,使用自己的私鑰進行解密,獲取對稱加密密鑰。在接下來的會話中,服務器和客戶端將會使用該密碼進行對稱加密,保證通信過程中信息的安全。
- 客戶端向服務端發(fā)送SSL協(xié)議版本號、加密算法種類、隨機數(shù)等信息。
- 服務端給客戶端返回SSL協(xié)議版本號、加密算法種類、隨機數(shù)等信息,同時也返回服務器端的證書,即公鑰證書
- 客戶端使用服務端返回的信息驗證服務器的合法性,包括:證書是否過期、發(fā)型服務器證書的CA是否可靠、返回的公鑰是否能正確解開返回證書中的數(shù)字簽名、服務器證書上的域名是否和服務器的實際域名相匹配、驗證通過后,將繼續(xù)進行通信,否則,終止通信
- 服務端要求客戶端發(fā)送客戶端的證書,客戶端會將自己的證書發(fā)送至服務端
- 驗證客戶端的證書,通過驗證后,會獲得客戶端的公鑰
- 客戶端向服務端發(fā)送自己所能支持的對稱加密方案,供服務器端進行選擇
- 服務器端在客戶端提供的加密方案中選擇加密程度最高的加密方式
- 將加密方案通過使用之前獲取到的公鑰進行加密,返回給客戶端
- 客戶端收到服務端返回的加密方案密文后,使用自己的私鑰進行解密,獲取具體加密方式,而后,產生該加密方式的隨機碼,用作加密過程中的密鑰,使用之前從服務端證書中獲取到的公鑰進行加密后,發(fā)送給服務端
- 服務端收到客戶端發(fā)送的消息后,使用自己的私鑰進行解密,獲取對稱加密的密鑰,在接下來的會話中,服務器和客戶端將會使用該密碼進行對稱加密,保證通信過程中信息的安全
工具是:Burp+Proxiey
設置好規(guī)則
想要的內容就收到了:
總結
為了搶個口罩也是不容易,硬生生的把 HTTPS 原理給整明白了,學無止境,希望對大家有所幫助。