使用 openssl 命令列工具解密 SSL 流量 - 續第 5 部分

使用 openssl 命令列工具解密 SSL 流量 - 續第 5 部分

從我之前的帖子第1部分,第2部分,第 3 部分第 4 部分我相信我已經正確計算/解密了所有內容,並準備好嘗試解密客戶端加密的握手訊息。一旦我擁有了所有的鑰匙,我就會陷入下一步。我已經閱讀和研究了幾天,但只是卡住了。

遵循我以前的帖子的指導方針,我想出了

20 bytes for a client MAC key: 64666eafe1cbd51f2e2b50799b40f6007c3dc56f
20 bytes for a server MAC key: e0aac1312d35b5e8b6bf9af6ecf07e1dff27c784
32 bytes client encryption key:
4bf20108190203c4210ff9df6c4eb6e907ddd1f49646ab4b243c80a6ae9b4808
32 bytes for a server encryption key:
 ca94445e3d771d3e06b71ee0deb4c1879986c4c6a4b78bf1c3c1083a6ddce9ff

我的加密客戶端握手訊息:

Hex.       FILE SIZE: 40
 ADDRESS   000 001 002 003 004 005 006 007       ASCII
===============================================================================
00000000   09A 01B 0F3 06B 078 06C 03B 059      ~Z  ^[  -s   k   x   l   ;   Y
00000008   085 061 07C 076 0AF 0D9 085 0D6      ~E   a   |   v  -/  -Y  ~E  -V
00000010   08F 0FD 0AF 06D 09F 01A 025 0EF      ~O  -}  -/   m  ~_  ^Z   %  -o
00000018   040 015 097 002 0B5 0AD 0EF 040       @  ^U  ~W  ^B  -5  --  -o   @
00000020   02B 0DB 051 096 0CE 076 0A9 03F       +  -[   Q  ~V  -N   v  -)   ?
00000028   0D7 030 049 03A 0CC 0F9 029 044      -W   0   I   :  -L  -y   )   D
00000030   07F 0A9 0C6 0F1 017 02D 06B 040      ^?  -)  -F  -q  ^W   -   k   @
00000038   035 0F5 057 08E 0BF 0E9 05C 06D       5  -u   W  ~N  -?  -i   \   m
00000040

我相信我需要使用 openssl end -d -K 的變體,但在 RFC 和 google 之間跌跌撞撞地找到了一個可以清楚解釋它的解決方案/範例。有誰知道如何/是否可以在 openssl 的命令列中執行此操作?謝謝

更新。我不確定為什麼/如何我忽略了RFC 7.4.9 PRF(master_secret, finished_label, Hash(handshake_messages))我確實記錄了所有握手訊息,有人可以解釋如何使用 openssl 命令列以及我到目前為止捕獲/解密的資料來模擬這一點嗎?看起來握手訊息的哈希值是我在此之前需要執行的操作RFC 第 5 節我假設我會使用我產生的 master_secret 我不確定它的種子應該是什麼,就像我之前使用它的方式一樣使用 openssl 。我沒有看到這個哈希有一個連接的標籤,所以我是否只使用連接在一起的所有握手訊息?我在很多地方都迷失了方向。謝謝

openssl dgst -sha256 -mac hmac -macopt hexkey:$key <seed -binary >a1

答案1

我很好奇你每次發文時似乎都使用新的文件轉儲格式:-)

假設您像以前一樣使用 (RSA-with-)AES256CBC-(HMAC)SHA1:是的,您可以使用以下命令解密 TLS CBC 密碼openssl enc,除了 ARIA。 (還有 RC4,儘管您應該避免將 RC4 用於包括 TLS 在內的任何目的。OTOHenc無法執行任何AEAD 密碼:不能使用GCM 或CCM,也不能使用ChaCha/Poly。)TLS1.2(和1.1)中的記錄格式CBC 密碼包含在RFC5246 第 6.2.3.2 節。對於 AES,前 16 個八位元組是 IV,其餘是密文,它應該解密為明文記錄正文(在本例中為 Finished 訊息)加上 HMAC 和填充 - 但 TLS 填充與 PKCS5/ 不同7 填充由API 支援enc(並由 API 內部支援EVP_{??crypt,Cipher}*),因此您需要自行完成該部分。

正如您系統上的手冊頁所述或在網路上,以及關於幾個堆疊的相當多的問題(儘管我注意到的大多數問題都是關於將命令行與其他程式碼(如 Java 和 python 等)匹配,而不是與規範匹配),openssl enc預設為基於密碼的加密(PBE),這不是您想要的。要進行「基於金鑰」的解密,您需要指定-d, -K(大寫而不是小寫)以及十六進位金鑰和-iv十六進位 IV(如果密碼使用的話)(AES-CBC 會這樣做):

$ echo $key; echo $iv
4bf20108190203c4210ff9df6c4eb6e907ddd1f49646ab4b243c80a6ae9b4808
9A1BF36B786C3B5985617C76AFD985D6
$ sed 1,2d <1346633.dat
8FFDAF6D9F1A25EF
40159702B5ADEF40
2BDB5196CE76A93F
D730493ACCF92944
7FA9C6F1172D6B40
35F5578EBFE95C6D
$ sed 1,2d <1346633.dat |xxd -p -r |openssl aes-256-cbc -d -K $key -iv $iv -nopad |xxd
0000000: f730 34cc b90f b0b0 6313 9a0f 239c 6e87  .04.....c...#.n.
0000010: 187f ff00 52d1 3e9c 2aef d5cd c07e 15be  ....R.>.*....~..
0000020: dee0 aa95 6994 5ce6 768d 1952 ac00 17ba  ....i.\.v..R....

不幸的是,正如您所看到的,此解密是無效的:它不是以 TLS 樣式的填充結束,也不是以 Finished 訊息開頭,而這是客戶端在 CCS 後進行的第一次傳輸。要么您的派生金鑰錯誤,要么您的該記錄轉儲錯誤。

一個可能有幫助的建議:使用以下命令建立連接(編輯) openssl s_client -debug並將其輸出記錄到文件中。這會轉儲十六進位(和 ASCII)的所有記錄,您可以將其用作資料或驗證各種輸入(包括包含 Finished 的加密記錄),並且末尾的「SSL-Session」區塊包括正確的值您可以將其用作交叉檢查的主秘密。您-msg也可以新增轉儲加密訊息;這比較笨重,但更方便,這就是我在下面所做的。另一種可能性是從使用 syspropjavax.net.debug=ssl和 log運行的 Java SSL/TLS (JSSE) 用戶端程式進行連接,需要進行更多的設定工作;那個轉儲地段包括主秘密在內的信息工作鍵。


作為一個例子來說明如何應該在工作中,我在記錄的範例會話上完成了該過程(實際上是我幾週前在您的第一個問題上創建的),手動進行了主推導和工作推導,並解密和驗證了客戶端的完成訊息:

$ cat tempc
2f e9 97 3e e4 11 89 81 c5 bc 18   11 7b c9 e9 3d
64 cb 88 6e a4 ac f2 01 95 05 d7
fe 3d 09 f4 13 4a d7 39 77 bf 50 dc f4 7b 9b b8
3c 0b 2f bf 98 5a 9c 4c 2d 28 6c 6a b6 93 a9 29
c5 5f f1 a3 cd
$ # this is the hexdump of from s_client -debug, cleaned up 
$
$ echo $key; echo $iv
7d18617e178fc6320019442c6cd071ca4b4f7d2bb83f6194c23681aefd84f120
2fe9973ee4118981c5bc18117bc9e93d
$ # you can see the IV is the first line (16 bytes) of tempc
$ sed 1d tempc |xxd -p -r |openssl aes-256-cbc -d -K $key -iv $iv -nopad |tee tempc! |xxd
0000000: 1400 000c 5bbc 39d8 6c5d dbb1 076b b91b  ....[.9.l]...k..
0000010: 9f4e 5c55 fd9e a185 6901 4bc0 6f02 2c0d  .N\U....i.K.o.,.
0000020: 5bb0 d8c9 0b0b 0b0b 0b0b 0b0b 0b0b 0b0b  [...............
$ # those last 12 bytes are SSL/TLS-style padding 
$ # the first 4 bytes are a handshake message header for x14=Finished,
$ # followed by the 12 byte verify_data value, total 16 bytes 
$
$ echo $mkey
28a3244d49c644f889b44f2bae54466b6913fb1e
$ { printf '\0\0\0\0\0\0\0\0\x16\x03\x03\0\x10'; head -c16 tempc! ; } \
> |openssl sha1 -mac hmac -macopt hexkey:$mkey -binary |xxd -p 
9f4e5c55fd9ea18569014bc06f022c0d5bb0d8c9
$ # the 20 bytes after the 16-byte message and before the padding 
$ # correctly match HMAC-SHA1 of the pseudoheader plus the message

至於'驗證數據'完成訊息,是的,您需要按照7.4.9 中的描述獲取所有先前握手訊息的哈希值(在TLS1.3 中,這稱為“轉錄”哈希值),然後獲取PRF(如之前的帖子中所述),其中以金鑰為主金鑰和種子是固定標籤「客戶端完成」或「伺服器完成」(如果適用)加上轉錄本雜湊。這是一項繁重的工作,我沒有在示例中這樣做,儘管如果有必要的話我可能可以這樣做。

相關內容