tls1.3協議實戰(一)---client hello和server hello解析


  1、根據公開資料顯示,xxxx的聊天通信協議mmtls是基於tls 1.3精簡了一些握手的方法后用openssl實現的;官方的介紹在這:https://mp.weixin.qq.com/s/tvngTp6NoTZ15Yc206v8fQ ;為了便於理解、抓住主脈絡,我這里整理了整個協議的主干思路,如下:

       

        

   既然是基於tls1.3改造的,為了更好的逆向分析xxxx的通信協議,這里先系統性地學習一下tls1.3協議!tls1.3協議官網地址:https://tools.ietf.org/html/rfc8446 對於新手,純看文檔估計頭都大了。為了便於理解,這里通過抓包來窺探tls1.3協議的細節和設計思路!
  2、我這里用chrome 74.0.3729.131,訪問google,wireshark抓到包后,隨便找一個tls1.3的client hello包,點擊右鍵,選擇追蹤流->TLS流,能看到完整的tls握手和數據發送的過程;
       

        完整的TLS流如下:

   

   下面挨個分析這些包的作用和重要字段的意義!

  (1)前面3個(195-197)tpc的包:有SYN、ACK等特征,很明顯是tcp3次握手的,這里不贅述了;整個TLS的過程,哪怕是0-RTT,都要先經歷TCP3次握手,只是不再進行TLS握手,直接發送應用數據
       (2)第198號包明顯與眾不同了:protocol是tls1.3,info標明了Client Hello,就是client主動找server打招呼,要開始通信了;
                第199號包:server馬山給client發確認收到client hello的消息。注意:server為啥要在0.1ms之內回復client,而不是直接發送server hello了? 從下面可以看出,server hello發送延遲到了第281號包,耗時約440ms。這么長時間的延遲,如果不提前給client發送確認包,client可能會認為自己發的hello包丟失,所以server先發個簡單的ACK,讓client知道已經收到了他的hello包,繼續耐心等待!
       第281號包:server給client發送server hello的包,同時標明“change cipher spec”,告訴client后續通信用對稱密鑰加密了!細心的讀者可能發現問題了:server在199號包給client發送了確認收到client hello的消息,但在第281號包才把server hello發給client,這期間操作系統已經發送了82個包,間隔大約440ms,這個耗時在公網通信中非常長了,為啥會延遲這么大了? 這里賣個關子,請繼續往下看!
   (3)從第282個包開始,server開始發送application data(猜測應該是網頁相關的數據,比如html、js、圖片、音視頻等文件),距離其發送server hello僅延遲0.1ms;從這里可以看出,client和server互相發送application data,僅耗費1-RTT,這也是tls1.3比tls1.2改進的地方(xxxx使用的mmtls協議采用的就是1-RTT的ECDH在client和server之間互相交換公鑰后生成了對稱密鑰);后面所有的包都是application data和ACK確認包(標明收到了對方的application數據)! 接下來又有問題了:HKDF、PSK、AES-GCM這些算法都在哪體現的了?( ̄▽ ̄)",下面挨個介紹通信中核心的數據以及原理!
 
  3、(1)client hello 包: 前面的3層:鏈路層、ip層、tcp層這里不再贅述,重點學習tls層的字段和含義
  •  老規矩,主動向server打招呼的時候先做個自我介紹:這個是handshake握手包,版本是1.0(我暫時也不知道為什么是這個),這個包的長度是512字節;(注意: tcp協議的缺點之一:必須明文指定包長度!接收方按照指定的長度讀取數據。windows下有個 CVE-2020-16898 "Bad Neighbor "  https://www.cnblogs.com/theseventhson/p/14004712.html  就是因為內核驅動沒處理好接受的數據包長度導致藍屏;這個地方還有可能利用整數溢出漏洞,進而導致緩沖區溢出)
  

   接下來是核心的handshake protocol解析,如下:字段有很多,我們挨個看

         

     前面3個handshake type、length、version都是常規的介紹,看英文不解釋都能懂!從第4個開始:

  •  random:client隨機生成一個32byte的數發給server。通常,在通信中以訪給另一方發隨機數的作用有:1)防止重放攻擊  2)后續用於完整性校驗,這里也不例外   3)生成encrypt-key,正式開始加密應用層的數據;
  •  session ID:雙方通信的一般套路都是“非對稱算法協商密鑰,對稱算法加密數據”。服務器生成session id,存放本次session協商好的對稱密鑰。下次通信時,客戶端帶上session id,server就知道用哪個對稱密鑰繼續加密數據了。不過session id有些缺陷(id一般都存在單個服務器,但客戶端的數據一般都是反向代理、負載均衡等轉發到內部某個server的,這些反向代理、負載均衡是不知道session id屬於哪個server),已經被session ticket替代;
  • cipher suites:client列舉自己支持的加密套件,可以看出前面一般是非對稱加密算法,協商對稱算法密鑰的。后面都是加密應用數據的對稱算法;后續server會根據自己的實際情況選擇合適的加密套件;這里稍微解釋一下這些加密套件的基礎算法,比如:0xc02b,ECDHE,是雙方用來協商對稱密鑰的橢圓曲線算法;ECDSA是客戶端驗證服務端的簽名算法;AES_128_GCM_SHA256是128bit的對稱加密算法,同時帶了數據校驗功能,可有效識別傳輸的數據是否被篡改!

          

  •  extension:有好多分項,都有不同的含義,先看第一個:說明server name。這里訪問的是gstatic,貌似是google的廣告聯盟站點。我並沒有訪問這個,估計是訪問google時自帶的;

        

  •  supported groups:由於安全性和效率問題,tls1.3已經不再使用RSA,而是橢圓曲線。不同的橢圓曲線對應不同的曲線形狀,會產生不同的公鑰;同樣,不同的基點G也會導致產生不同的公鑰,所以這里有4種不同的橢圓曲線參數供client選擇;

  

  • session ticket:作用和session id類似,上面已經解釋過了。這里由於還是client hello階段,所以這個字段暫時沒有值;保留字段,帶上空值,也可以向服務器標明client支持session ticket功能

   

  •  application layer protocol negotiation:協商tls上層的應用層協議,這里采用的是http協議

       

  •  key share:這個是重點!tls1.3支持1-RTT,比tls1.2效率提升一倍,原因就在這里了:在client hello里面,client列舉出了自己支持的加密套件,並把所有的非對稱加密算法的公鑰都一並帶上(雖說這里只有1種,我懷疑是瀏覽器的問題)。server收到后可以直接根據接受的ECDHE和client的公鑰生成自己的公鑰和對稱密鑰

        

  •  PSK exchange models:psk_dhe_ke=1,這里雙方約定用非對稱加密方法ECDHE協商一個對稱密鑰,或則直接從之前協商出來的密鑰參數中得出一個密鑰(psk_ke);

      

  •  supported version:支持的tls版本,這里大概是為了兼容老版本,從tls1.0到1.3都支持

      

  •  pre-shared key:訪問googke另一個分站點的時候,抓到了PSK的字段,如下:(1)psk本質也是一串ID,這里有226byte,生成方式見本文上方的那張圖,最早是server和client通過tls成功握手后把key和其他一些信息通過HMAC轉換后發給client;client后續訪問可以直接帶上這個PSK,就不用再做密鑰協商,節約時間;(2)這里還有個obfuscated ticket age: 1874391131,轉成年月日的格式就是2029-05-25 16:12:11,這是PSK的生存時間,過期就用不了了

            

  注意幾個容易混淆的概念:

  • key_share:橢圓曲線中雙方互換公鑰來生成對稱加密的私鑰; pre_shared_key:是預共享秘鑰認證機制PSK生成的對稱秘鑰,PSK也是一種身份認證機制;
  • psk其實即使Session ticket外加一些檢驗的東西,相當於ticket的強化版!

  上面介紹了那么多extension,有4個extension是必須的:psk_key_exchange_modes、pre_shared_key、key_share、supported_versions;

 

  (2)server hello:先來看前面遺留的第一個問題:為啥client hello之后server先發一個ack給client,再發server hello了?而不是直接發個server hello?

   

   server hello要根據client的加密套件、公鑰繼續算出自己公鑰和私鑰(32byte=258bit),這種big num的計算是相當耗時的(這里花了約440ms)。如果server在收到client hello后不馬上回復ACK,而是等計算出自己公鑰和私鑰再回復client,搞不好client會認為server已經超時掛掉,所以server先發個ACK,讓client知道他的hello包已經被收到

  和分析client hello包一樣,接下來挨個分析重要字段的含義:

  • 還是標明這個包的作用是handshake,長度122字節,版本是1.2(也不知道為啥不標注1.3)......

  

  •  Random: 32byte的隨機數,作用和之前client發給server的隨機數一樣,1)防止重放    2)后續用於消息完整性校驗,防止被篡改   3)生成encrypt-key,正式開始加密應用層的數據;

          

  •  session id:32byte,作用在client那里已經解釋了

   

  •   Cipher Suite:client在client hello包里面列舉了其能支持的加密套件,這里server在里面選擇了這個加密套件;后續雙方就用AES_GCM來做對稱加密

        

  •   Extensions:最重要的莫過於key_share了。對稱加密算法是AES_GCM,那么密鑰又是啥了? 就是通過橢圓曲線計算出來的;Client在hello包里已經給server發送了他的公鑰,server也要把自己的公鑰發給client,雙方才能計算出對稱加密的密鑰,所以server這里選擇了x25519(這個其實是client選擇的,server只能遵從)

        

  • Change Cipher Spec:告訴client,后續咋們通信時改變現在的加密方式,即改成對稱密鑰加密通信數據

      

    剩下的問題又來了:wireshark就解析到了0xba這個位置,從0xbb到0x58e=1422的位置,還有1234byte並未解析,這些又都是什么數據了?縱觀整個協議的握手過程,截至目前看到的都是handshake密鑰交換階段,record傳輸加密數據的階段都在哪了? 

        4、總結:

  (1) 剛開始學的時候,對session id、ticket、psk理解不夠透徹,很多概念的解釋看的雲里霧里,這里系統性對比和總結這3個概念的區別,希望對讀者有所幫助;

    

   (2)整個過程涉及到client和server雙方互換公鑰和生成對稱密鑰。期間只有client驗證server,並沒有server驗證client,這里有個缺陷:如果黑客冒充client(這個不難,比如隨機更換源IP,導致server認為是來自不同client的包),隨機生成各種公鑰(甚至都不用隨機生成,而是直接寫死),server接收到client的公鑰后要需要耗費算計去計算對稱密鑰。如果黑客偽造的client達到一定數量,理論上可以導致server的CPU耗盡,無法再接受正常client的鏈接請求,這也是常見的DOS攻擊之一!

 

參考:

1、https://blog.csdn.net/SkyChaserYu/article/details/105840504  tls1.3抓包分析

2、https://time.geekbang.org/comment/nice/111287  session id、session ticket、psk三者區別和聯系

3、https://halfrost.com/https_tls1-3_handshake/ 直觀感受tls握手流程

4、https://jasonlees.netlify.app/article/tcpip-4-ssl-tls-3/   TCP/IP系列(4)-SSL/TSL詳解(3)

5、https://cshihong.github.io/2019/05/09/SSL%E5%8D%8F%E8%AE%AE%E8%AF%A6%E8%A7%A3/  SSL協議詳解

 


免責聲明!

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



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