Entschlüsseln Sie SSL-Datenverkehr mit dem Befehlszeilenprogramm openssl - Fortsetzung Teil 5

552
David B

Von 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, die verschlüsselte Client-Handshake-Nachricht zu entschlüsseln. Ich bin auf dem nächsten Schritt fest, sobald ich alle Schlüssel habe. Ich habe das seit ein paar Tagen gelesen und recherchiert und bin einfach festgefahren.

Befolgen Sie die Richtlinien aus meinen vorherigen Beiträgen, die ich mir ausgedacht habe

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, stolpere hier jedoch zwischen RFC und Google, um eine Lösung / ein Beispiel zu finden, die dies eindeutig erklärt. Weiß jemand wie / ob ich das an der Kommandozeile in openssl machen kann? Vielen Dank

Aktualisieren. Ich bin mir nicht sicher, warum / wie ich im RFC 7.4.9 übersehen habe.PRF(master_secret, finished_label, Hash(handshake_messages)) Ich habe alle Handshake-Nachrichten protokolliert. Kann jemand erklären, wie ich dies mit der OpenSL-Befehlszeile simulieren kann, mit den Daten, die ich bis zu diesem Punkt erfasst / entschlüsselt habe? Anscheinend ist der Hash der Handshake-Nachrichten das, was ich vor diesem RFC-Abschnitt 5 durchführen muss. Ich gehe davon aus, dass ich das von mir generierte master_secret verwenden werde. Ich bin mir nicht sicher, was der Grund dafür ist, der OpenSSL so zu verwenden Ich habe es schon früher benutzt. Ich sehe nicht, dass für diesen Hash ein Label verkettet ist. Benutze ich also alle Handshake-Nachrichten, die an diesem Punkt miteinander verkettet sind? Es gibt viele Schritte, an denen ich mich verliere, wo ich bin. Vielen Dank

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

1 Antwort auf die Frage

1
dave_thompson_085

Ich bin fasziniert, dass Sie bei jedem Beitrag ein neues File-Dump-Format zu verwenden scheinen :-)

Angenommen, Sie verwenden (RSA-with-) AES256CBC- (HMAC) SHA1 wie zuvor: Ja, Sie können TLS-CBC-Verschlüsselungscodes 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 verwenden: Nicht GCM oder CCM und nicht ChaCha / Poly.) Das Datensatzformat in TLS1.2 (und 1.1) für a CBC-Verschlüsselung wird in Abschnitt 6.2.3.2 von RFC5246 behandelt . Bei AES sind die ersten 16 Oktette die IV und der Rest der Schlüsseltext, der zum Haupttext des Klartextdatensatzes (in diesem Fall der Nachricht Finished) plus HMAC plus Auffüllen entschlüsseln sollte. Die TLS-Auffüllung entspricht jedoch nicht der von PKCS5 / 7 Padding wird von enc(und intern von der EVP_{??crypt,Cipher}*API) unterstützt, sodass Sie diesen Teil selbst durchführen müssen.

Wie in der Manpage auf Ihrem System oder im Web beschrieben, und einige Fragen zu mehreren Stacks (obwohl die meisten, die ich bereits erwähnt habe, über das Abgleichen der Kommandozeile mit anderem Code wie Java und Python usw., aber nicht mit einer Spezifikation) erfolgen, wird openssl encstandardmäßig das Kennwort verwendet -basierte Verschlüsselung (PBE), das ist nicht das, was Sie hier wollen. Zu tun ‚schlüsselbasierte‘ Entschlüsselung, müssen Sie angeben -d, -K(Groß- Klein nicht) mit dem Schlüssel in hex, und -ivmit den IV in hex, wenn durch die Chiffre verwendet (AES-CBC Fall ist):

$ 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 können, ist diese Entschlüsselung leider ungültig: Sie endet nicht mit TLS-artigem Padding, und sie beginnt nicht mit einer Fertig-Nachricht. Dies ist, was die erste Post-CCS-Übertragung durch den Client sein muss. Entweder ist Ihr abgeleiteter Schlüssel falsch oder Ihr Speicherauszug dieses Datensatzes.

Ein Vorschlag, der möglicherweise hilfreich ist: Herstellen einer Verbindung mit (Bearbeiten) openssl s_client -debug und Protokollieren der Ausgabe in eine Datei. Dadurch werden alle Datensätze in hexadezimaler Form (und ASCII) gesichert, die Sie als Daten verwenden oder zur Überprüfung der verschiedenen Eingaben verwenden können (einschließlich des verschlüsselten Datensatzes, der Finished enthält), UND der 'SSL-Session'-Block am Ende enthält den korrekten Wert von Meistergeheimnis, das Sie als Gegenprobe verwenden können. Sie können hinzufügen, -msgum auch die verschlüsselten Nachrichten auszugeben. Dies ist etwas umfangreicher, aber etwas bequemer und habe ich unten gemacht. Eine weitere Möglichkeit, etwas mehr Arbeit beim Einrichten, besteht in der Verbindung von einem Java-SSL / TLS-Clientprogramm (JSSE), das mit sysprop javax.net.debug=sslund dem Protokoll ausgeführt wird. Dadurch werden viele Informationen ausgegeben, einschließlich des Hauptgeheimnisses und der Arbeitsschlüssel.


Als Beispiel dafür, wie dies funktionieren sollte, habe ich die Prozedur einer protokollierten Beispielsitzung (die ich vor einigen Wochen bei Ihrem ersten Q erstellt habe) durchlaufen, die Master- und Arbeitsableitungen von Hand gemacht und die Fertig-Nachricht des Clients entschlüsselt und überprüft :

$ 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 Finished-Nachricht angeht, müssen Sie den Hash aller vorherigen Handshake-Nachrichten wie in Abschnitt 7.4.9 (in TLS1.3 wird dies als 'Transkript'-Hash bezeichnet) und dann die PRF ( wie in den vorherigen Beiträgen beschrieben), wobei der Schlüssel das Hauptgeheimnis ist und der Startwert das festgelegte Label 'Client beendet' oder 'Server beendet' (falls zutreffend) plus diesen Transkripthash ist. Das ist viel mehr Arbeit und ich habe es nicht für das Beispiel gemacht, obwohl ich es wahrscheinlich tun kann.

Dave, danke ... da ich nicht sicher bin, welcher Schritt in meinem Shellskript falsch ist, den Schlüssel abzuleiten. Ich habe meinen ersten Schritt hier veröffentlicht. Kannst du einen Blick darauf werfen, ob ich vielleicht meinen Client nicht korrekt verschlüsselt erfasst habe? Das ist das einzige, woran ich denken kann, was ich falsch gemacht habe. Vergleiche das, was ich sehe In wireshark und in der Datei, die ich byte für byte erstellt habe, sind sie genau. [hier] (https://superuser.com/questions/1347188/decrypt-ssl-traffic-with-the-openssl-command-line-tool-6) sind die Daten einschließlich meines privaten Schlüssels. David B vor 5 Jahren 0
ps Ich folgte Ihrer Gliederung bis zu einem "t", indem ich die Daten verwendete, die Sie im Beispiel für $ key und $ lbsd angegeben haben, um sicherzustellen, dass ich genau das gleiche Ergebnis habe. Mein Shellskript basiert auf den meisten, mit Ausnahme einiger Dinge. Dann erweitern Sie das auf die Tasten. David B vor 5 Jahren 0