Entschlüsseln Sie den SSL-Verkehr mit dem Befehlszeilentool openssl - Fortsetzung Teil 5


1

Aus meinen vorherigen Beiträgen Teil 1 , Teil 2 , Teil 3 und Teil 4 glaube ich, dass ich alles richtig berechnet / entschlüsselt habe und bereit bin, zu versuchen, die Client-verschlüsselte Handshake-Nachricht zu entschlüsseln. Ich stecke beim nächsten Schritt fest, wenn ich alle Schlüssel habe. Ich lese und recherchiere das seit ein paar Tagen und stecke einfach fest.

Befolgen Sie die Richtlinien aus meinen vorherigen Beiträgen

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

Meine verschlüsselte Client-Handshake-Nachricht:

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

Ich glaube, ich muss eine Variation von openssl end -d -K verwenden, aber hier zwischen dem RFC und Google herumstolpern, um eine Lösung / Beispiel zu finden, die es klar erklärt. Weiß jemand, wie / ob ich dies in der Befehlszeile in openssl tun kann? Vielen Dank

Aktualisieren. Ich bin mir nicht sicher, warum / wie ich in RFC 7.4.9 übersehen habe.PRF(master_secret, finished_label, Hash(handshake_messages)) Ich habe alle Handshake-Nachrichten protokolliert. Kann mir jemand erklären, wie ich dies mit nur einer openssl-Befehlszeile mit den Daten simulieren kann, die ich bis zu diesem Punkt erfasst / entschlüsselt habe? Es sieht so aus, als ob der Hash der Handshake-Nachrichten das ist, was ich vor diesem RFC-Abschnitt 5 ausführen muss. Ich gehe davon aus, dass ich das von mir generierte master_secret verwenden werde Ich habe es vorher benutzt. Ich sehe nicht, dass für diesen Hash ein Label verkettet ist. Verwende ich also alle Handshake-Nachrichten bis zu diesem Punkt zusammen verkettet? Es gibt viele Schritte, bei denen ich mich verliere. Vielen Dank

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

Antworten:


2

Ich bin fasziniert, dass Sie jedes Mal, wenn Sie etwas posten, ein neues File-Dump-Format verwenden :-)

Angenommen, Sie verwenden wie zuvor (RSA-with-) AES256CBC- (HMAC) SHA1: Ja, Sie können TLS-CBC-Chiffren mitopenssl enc Ausnahme von ARIA entschlüsseln . (Auch RC4, obwohl Sie RC4 für keinen Zweck einschließlich TLS verwenden sollten. OTOH enckann keine AEAD-Chiffren ausführen : nicht GCM oder CCM und nicht ChaCha / Poly.) Das Aufzeichnungsformat in TLS1.2 (und 1.1) für a Die CBC-Verschlüsselung wird in RFC5246 Abschnitt 6.2.3.2 behandelt . Für AES sind die ersten 16 Oktette die IV und der Rest der Chiffretext, der in den Klartext-Datensatzkörper (in diesem Fall in die Fertige Nachricht) plus HMAC plus Auffüllung entschlüsselt werden soll. Die TLS-Auffüllung ist jedoch nicht mit der PKCS5 / identisch. 7 padding wird von enc(und intern von der EVP_{??crypt,Cipher}*API) unterstützt, daher müssen Sie diesen Teil selbst ausführen.

Wie in der Manpage auf Ihrem System oder im Web beschrieben und in einigen Fragen zu mehreren Stacks (obwohl die meisten, die ich notiert habe, die Zuordnung der Befehlszeile zu anderem Code wie Java und Python usw. betreffen, nicht zu einer Spezifikation), wird openssl encstandardmäßig ein Kennwort verwendet -basierte Verschlüsselung (PBE), die Sie hier nicht wollen. Um die 'schlüsselbasierte' Entschlüsselung durchzuführen, müssen Sie (Groß- und Kleinschreibung) angeben -d, -Kwobei der Schlüssel hexadezimal und -ivdie IV hexadezimal ist, wenn sie von der Verschlüsselung verwendet wird (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....

Wie Sie sehen, ist diese Entschlüsselung leider ungültig: Sie endet nicht mit einer Auffüllung im TLS-Stil und beginnt nicht mit einer beendeten Nachricht, wie es die erste Post-CCS-Übertragung durch den Client sein muss. Entweder ist Ihr abgeleiteter Schlüssel falsch oder Ihr Speicherauszug dieses Datensatzes ist.

Ein Vorschlag, der helfen könnte: Stellen Sie eine Verbindung mit (Bearbeiten) her openssl s_client -debug und protokollieren Sie die Ausgabe in einer Datei. Dadurch werden alle Datensätze in hexadezimaler Schreibweise (und in ASCII-Schreibweise) ausgegeben, die Sie als Daten für die verschiedenen Eingaben oder zur Überprüfung der Eingaben verwenden können (einschließlich des verschlüsselten Datensatzes mit dem Wert "Finished"), UND der Block "SSL-Session" enthält am Ende den korrekten Wert von Hauptgeheimnis, das Sie als Gegenprobe verwenden können. Sie können hinzufügen, -msgum auch die verschlüsselten Nachrichten zu sichern. Dies ist voluminöser, aber ein bisschen praktischer und ist das, was ich unten getan habe. Eine andere Möglichkeit, die ein wenig aufwändiger zu konfigurieren ist, besteht darin, eine Verbindung über ein Java SSL / TLS-Clientprogramm (JSSE) herzustellen, das mit sysprop javax.net.debug=sslund log ausgeführt wird. das wirft eine Menge Informationen ab, einschließlich des Hauptgeheimnisses und der Arbeitsschlüssel.


Als ein Beispiel dafür , wie dies sollte arbeiten, ging ich durch das Verfahren auf einer Sitzung angemeldet Probe (was ich eigentlich vor ein paar Wochen auf dem ersten Q erstellt), von Hand zu tun und die Master - Arbeit Ableitungen und Entschlüsseln und Verifizieren des Finished Nachricht des Kunden :

$ 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

Was die 'verify_data' in der fertigen Nachricht betrifft, müssen Sie den Hash aller vorherigen Handshake-Nachrichten wie in 7.4.9 beschrieben nehmen (in TLS1.3 wird dies als 'Transcript'-Hash bezeichnet) und dann den PRF ( wie in den vorherigen Beiträgen beschrieben), wobei der Schlüssel das Hauptgeheimnis ist und der Startwert die feste Bezeichnung "Client beendet" oder "Server beendet" (sofern zutreffend) plus dieses Transkript-Hash ist. Das ist viel mehr Arbeit und ich habe es nicht für das Beispiel getan, obwohl ich es wahrscheinlich tun kann, wenn es nötig ist.


Dave, danke ... da ich nicht sicher bin, welcher Schritt in meinem Shell-Skript falsch sein könnte, wenn ich den Schlüssel ableite. Ich habe hier meinen ersten Schritt gepostet. Können Sie einen Blick darauf werfen, ob ich meinen clientverschlüsselten Premaster möglicherweise nicht richtig erfasst habe? Das ist das einzige, woran ich denken kann, dass ich etwas falsch gemacht habe. Vergleicht man, was ich in Wireshark sehe, und die Datei, die ich Byte für Byte erstellt habe, sind genau, damit ich nicht glaube, dass mein erster Schritt falsch ist. Hier sind die Daten einschließlich meines privaten Schlüssels.
David B

ps Ich bin Ihrer Gliederung zuerst mit den Daten gefolgt, die Sie im Beispiel für $ key und $ lbsd angegeben haben, um sicherzustellen, dass ich genau das gleiche Ergebnis erzielt habe. Mein Shell-Skript basiert mit Ausnahme einiger Dinge größtenteils darauf. Erweitern Sie das dann zu den Schlüsseln.
David B
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.