[轉]HTTPS網絡流量解密方法探索系列(一)


前言

分析網絡流量總是繞不開HTTPS,因其廣泛使用甚至是強制使用逐漸被大眾熟知,在保證其安全的同時也提高了對流量進行研究的難度。目前解析HTTPS協議的文章很多,有很多不錯的文章可以帶着入門,老實說,HTTPS協議還是挺復雜的,尤其是握手交換密鑰的過程;雖然大部分的文章只是對協議握手的過程做了詳細的解析,卻很少涉及HTTPS網絡數據包解密的部分,因此,本文即是從數據包層面,在知道私鑰的情況下,來一步一步看如何對HTTPS的內容進行解密。

正文

要對HTTPS網絡數據包進行解密,其實是有一些工具是可以使用的,比如wireshark和ssldump,現在,先讓我們來看看這兩款工具如何使用,在手動對HTTPS的數據包進行解密。

1.wireshark解密HTTPS數據包

首先是wireshark,在wireshark界面上方,依次點擊 編輯->首選項。

image.png

再點擊Protocols 找到SSL,並進行必要配置:

image.png

先是對RSA keys list進行編輯,點擊Edit完成配置,如下所示:

image.png點擊加號,依次配置(服務器IP、目的端口、應用層協議、私鑰路徑)。然后對SSL debugfile進行配置,在這里面,wireshark會打印出解密過程中的調試信息,非常有用,后文在進行手動解密的時候即是通過它發現的錯誤,按照前文配置到一個路徑下,配置完成點擊ok后,可在wireshark主界面解密出通信內容。 
image.png

如圖所示,順利解出了HTTP的內容,在大呼神奇的同時,我們對它的解密過程卻一無所知,這其實是不利於學習的,所以本文即是來掃除這些盲點。下面我們再來看看ssldump工具的使用。

ssldump是一款Linux下的小工具,可直接用apt包管理工具安裝,目前最新版本是ssldump0.9b3(13年后就停止更新了,可以下載源碼)。在shell中運行:

ssldump -Ad -k./private.pem -r ./ssl.pcap

該條命令會打印出部分的解密過程,如下圖所示:

image.png

從該圖中可以看到client/server產生的隨機數(random),加密的預主密碼(EncryptedPremaster secret),以及用到的加密套件,為:

TLS_RSA_WITH_AES_256_CBC_SHA

表示采用RSA進行身份認證和對稱密鑰交換,采用AES 256位對稱加密算法,加密模式為CBC,采用SHA進行消息認證。雖然工具已經解出了HTTP的請求內容,但是打印信息中未打印出解密后的主密碼和對稱密鑰,因此,打印信息沒有完整反映解密過程,這款工具在centos下還會出現core dumped錯誤,感覺不是太好用。

2.HTTPS協議簡介

雖然已經有不少的帖子非常詳細地介紹了HTTPS協議,但是本文依然選擇簡單介紹一下HTTPS協議,主要側重於對解密中要用到的參數進行說明。如下圖所示,為HTTPS完整握手的流程圖。

image.png

圖中完整地反映了HTTPS的握手過程,在此過程中,Client會同Server交互若干參數來協商對稱密鑰,用來對應用數據進行加解密。這里筆者以TLS_RSA_WITH_AES_256_CBC_SHA這個密碼套件為例,講述整個解密過程。那么,解密過程需用到的參數如下:

1.clientrandom 客戶端隨機數;

2.serverrandom 服務器隨機數;

3.EncryptedPreMaster 加密的預備主密碼。

image.png

如上圖所示,解密的過程大致為:先用私鑰對Encrypted PreMaster Secret進行解密,得到decrypted PreMaster Secret;再用client random、server random、decrypted PreMaster 得到Master Secret;再用MasterSecret計算出消息認證密鑰(key of MAC)、數據加密對稱密鑰和CSC模式用到的初始化向量值(iv),得到密鑰后即可對通信內容進行解密了。看似過程很簡單,實際上只有實驗一把才會更好理解整個過程。

3.HTTPS網絡數據包手動解密

在解密之前,需要說明的是,並不需要自己寫解密代碼來完成數據的解密,有很多好用的工具可以完成這件事,我們需要做的是,把整個流程串起來即可。本文中所使用的解密工具為openssl,很強大的工具,用它完成非對稱加解密和對稱加解密是相當方便的。

實驗准備:本文的流量樣本采用的TLS1.0版本,雖然目前主流是用TLS1.2,但是這兩個版本基本框架一致,弄懂了前者,后者也是很好理解的,流程稍作改動同樣能完成解密;以學習為目的,從1.0開始是一個不錯的選擇。本文流量的加密套件采用RSA非對稱加密交換對稱密鑰參數,采用AES256對通信流量進行加密。所有的實驗材料已上傳到github中。

那就正式開始吧,首先是在數據包中將client random,server random和Encrypted PreMaster的二進制數據提取出來。如下圖所示,在wireshark中分別找到clienthello、serverhello、clientkey exchange數據包,選擇要導出的字段,點擊鼠標右鍵,選擇導出分組字節流,存成bin文件,分別為client_random.bin、server_random.bin、premaster-encrypted.bin。

image.png在Ubuntu中查看結果,這三個二進制文件的內容分別為:

image.png

首先,是對premaster-encrypted.bin進行解密。利用已獲得的私鑰private.pem進行解密,解密命令為:

openssl pkeyutl -decrypt -in ./premaster-encrypted.bin -inkey ./private.pem -out premaster-decrypted.bin

如未報錯,代表執行成功,將解密的數據存入到premaster-decrypted.bin文件中,用hexdump可查看。

image.png

就得到解密后的預備主密碼,對於密碼專家來說,得到預備主密碼跟最后一步解密內容是等價的。但對於我們來說,還有幾步要折騰。

下一步,即是利用預備主密碼計算主密碼,在此過程中,還需利用clientrandom和serverrandom,用命令將client_random.bin,server_random.bin兩個文件合並起來。

cat client_random.bin server_random.bin > random_cs.bin

用hexdump查看有如下結果:

image.png

然后用偽隨機函數計算(PRF)計算主密碼,偽隨機函數計算程序需在windows下運行,命令如下。

.\PRF.exe--label "master secret" --length 48 --secret.\premaster-decrypted.bin --data .\random_cs.bin  --output master-secret.bin

PRF.exe為網上分享的計算程序,源程序見這里,本文的github中已作分享。利用這款程序就可得到主密碼文件master-secret.bin,用hexdump查看為:

image.png

這種計算主密鑰的方法存在漏洞,在TLS1.2版本中已做調整。接下來,就可以利用主密碼計算加密傳輸數據的對稱密鑰和其他參數了。在解密之前,需要用先生成random_sc.bin,如下:

cat server_random.bin client_random.bin > random_sc.bin

與上一個文件不同的是client random和server random的順序不一樣,得到random_sc.bin。然后,同樣在windows下運行,命令如下:

.\PRF.exe--secret .\master-secret.bin --label "key expansion" --data.\random_sc.bin -n 136 -o key-expansion.bin

得到key-expansion.bin文件,用hexdump查看為:

image.png

這樣利用主密碼生成了6種信息,分別是:

20字節的消息認證碼密鑰(客戶端→服務器)

20字節的消息認證碼的密鑰(服務器→客戶端)

32字節的對稱密碼密鑰(客戶端→服務器)

32字節的對稱密碼的密鑰(服務器→客戶端)

16字節的對稱密碼的CBC模式所使用的初始化向量(客戶端→服務器)

16字節的對稱密碼的CBC模式所使用的初始化向量(服務器→客戶端)

字節數加起來剛好同key-expansion.bin文件的字節數吻合,在此,就得到了對稱加密時所使用的密鑰。客戶端到服務器的對稱密鑰為:

a86b855b66c5dc18566879eb98e8a86b7c90c5564438f3af80b317dcb5a25747

現在我們就可以用它來解密客戶端到服務器的應用數據內容。在正式解密前,我們先按照上述方法將客戶端到服務端的應用層數據提取成二進制文件,為client-request.bin,然后用如下命令進行解密:

openssl enc-aes-256-cbc -d -K $cs_key -iv $iv_value -in .\client-request.bin -out.\client-request-decrypted.bin

其中,$cs_key為客戶端到服務器傳送消息的密鑰,iv為上一個消息內容中最后一個分組的值,iv的值僅憑這句話,不太好找,我也是試出來的。確定iv值的方法如下所示:

image.png圖中第24個數據包為要解密的內容,上一個消息指的是客戶端到服務器方向的上一個消息,也即是第20個包,最后一個分組的值為該數據包最后16個字節,如下圖所示:

image.png第20個數據包的最后一個分組,即iv就是: ed605d761378241c7add3c921022b268。需要說明的是,iv值的計算方法在TLS1.0版本存在漏洞,在TLS1.2版本中已做更改。得到iv就可執行解密命令,並將解密內容存在client-request-decrypted.bin文件中,用hexdump和cat查看:

image.png

如上圖所示,順利解出HTTP協議的請求內容,最后有一段亂碼,那是HMAC的值,做消息認證用,感興趣的朋友可以自己去看消息認證相關內容,這里只需解出明文數據就行了。對於服務器到客戶端的消息,采用同樣的方法,也可以解出來,但用到的是服務器到客戶端的密鑰。

大家照着這個流程可以很快地復現出來,但筆者在此過程中踩過很多坑,有時也不知道哪一步計算錯了,由於只要任何一部出錯,后面的都不對,挺折騰的。不過,要解決調試問題,wireshark的debug文件很有用,里面把每一步需要計算的參數都打印出來了,部分結果如下圖所示:

image.png

client write key就是客戶端到服務器的對稱加密密鑰,同我們計算的一樣。因此,可對照着debug文件的結果,查看哪一步算錯了,這可以幫助開發人員快速定位到問題。

既然手動能解出來,那下一步就是自動化實現了,這也不難,openssl提供有C和Python開發庫,復雜的密碼算法不用我們來實現,調用API解密函數即可。在以后的系列篇中,即是完成自動解密程序,以及加上對TLS1.2的支持。

總結

HTTPS協議是比較復雜的一個協議,要想學習它,光看它的技術原理是不得要領的,本文也是筆者在對它學習的過程中產生。嘗試通過手動解密HTTPS數據包的過程是很有趣的,也能加強對HTTPS協議的理解。其中關於數字證書驗證和消息認證本文沒有涉及,由讀者自己去研究了。對HTTPS協議的研究,大家如有其它的點,歡迎一起討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM