AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials SSL/TLS-Kommunikation aus Indy 10 mit Wireshark entschlüsseln

SSL/TLS-Kommunikation aus Indy 10 mit Wireshark entschlüsseln

Ein Tutorial von Codehunter · begonnen am 7. Mär 2019
Antwort Antwort
Benutzerbild von Codehunter
Codehunter
Registriert seit: 3. Jun 2003
Hallo!

Aus ursprünglich einer Frage von mir im Netzwerke-Board ist ein kleines Projekt entstanden.

Wenn man mittels Indy mit externen Diensten Daten austauscht, hat man es heutzutage oftmals mit SSL/TLS-gesicherten Verbindungen zu tun. Gerade beim Debugging kann das ziemlich hinderlich sein, wenn der Server eine Anfrage abweist und man nur sehr umständlich heraus findet, woran es scheitert.

Die meisten modernen Webbrowser unterstützen das Schreiben einer NSS-Datei. Dank dessen konnte ich verschlüsselte Verbindungen mittels Wireshark einsehen. Beispielsweise das Projekt FMC wurde dadurch überhaupt erst möglich.

Nun wollte ich gerne mit eigenen HTTP-Clienten ebenso verfahren und eine solche NSS-Datei erstellen. Das erwies sich als erstaunlich schwierig, weil es in der von mir verwendeten Indy-10-Bibliothek einen Bug gab.

Nachdem das aus der Welt geschafft war, ist das Erstellen einer NSS-Datei mit Indy eigentlich ganz einfach. Auf das Grundgerüst eines HTTPS-Clients gehe ich hier nicht weiter ein, dafür gibt es bereits Tutorials. Letzten Endes hat man eine TIdSSLIOHandlerSocketOpenSSL-Instanz. Diese verfügt über ein Ereignis namens OnStatusInfoEx. Dieses Ereignis verwenden wir für unser SSL-Keylog.

Delphi-Quellcode:
uses
  IdSSLOpenSSL, IdSSLOpenSSLHeaders;
const
  FNSSFilePath = 'C:\Log\SSLKEYLOG.LOG';
var
  FLastNSSLine: AnsiString;

procedure TForm1.DoSSLStatusInfoEx(ASender: TObject;
  const AsslSocket: PSSL; const AWhere, Aret: Integer; const AType,
  AMsg: string);
var
  LMasterByte, LRandomByte: Byte;
  LRandomChar: AnsiChar;
  LMasterSecret, LClientRandom, LLogLine: AnsiString;
  LMode: Word;
  LFileStream: TFileStream;
  LS3: Pssl3_state;
begin
  if AWhere = SSL_CB_HANDSHAKE_DONE then begin
    LS3 := AsslSocket^.s3;
    Dec(PByte(LS3)); // <-- Bug in IdSSLOpenSSLHeaders.pas Deklaration write_mac_secret : array [0..EVP_MAX_MD_SIZE] of TIdAnsiChar; // muss [0..EVP_MAX_MD_SIZE - 1] lauten
    for LRandomChar in LS3.client_random do begin
      LRandomByte := Ord(LRandomChar);
      LClientRandom := LClientRandom + AnsiString(Format('%2.2x', [LRandomByte]));
    end;
    for LMasterByte in AsslSocket^.session^.master_key do begin
      LMasterSecret := LMasterSecret + AnsiString(Format('%2.2x', [LMasterByte]));
    end;
    LLogLine := 'CLIENT_RANDOM ' + LClientRandom + ' ' +
                LMasterSecret + sLineBreak;
    if LLogLine <> FLastNSSLine then begin
      LMode := (fmOpenReadWrite or fmShareDenyNone);
      if DirectoryExists(ExtractFilePath(FNSSFilePath)) then begin
         if not FileExists(FNSSFilePath) then begin
          LMode := fmCreate or LMode;
        end;
        LFileStream := TFileStream.Create(FNSSFilePath, LMode);
        try
          LFileStream.Position := LFileStream.Size;
          LFileStream.Write(LLogLine[1], Length(LLogLine));
          Exit;
        finally
          FLastNSSLine := LLogLine;
          FreeAndNil(LFileStream);
        end;
      end;
    end;
  end;
end;
OnStatusInfoEx wird während einer Verbindung mehrfach aufgerufen. Deshalb prüfen wir den Verbindungsstatus mit if AWhere = SSL_CB_HANDSHAKE_DONE auf den richtigen Moment. Anschließend erzeugen wir mittels zweier Schleifen aus den beiden Arrays AsslSocket^.s3.client_random und AsslSocket^.session^.master_key zwei Strings und bauen daraus die neue Zeile für die NSS-Datei zusammen. Diese schaut dann in etwa so aus:
Code:
CLIENT_RANDOM 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
Die SSL-Schlüssel werden jedoch nicht bei jeder weiteren HTTPS-Anfrage, die wir mit unserem Indy-Client absetzen, neu ausgehandelt sondern teilweise wiederverwendet. Damit wir also nicht mehrfach die selben NSS-Einträge schreiben, benutze ich hier einfach eine globale AnsiString-Variable FLastNSSLine und prüfe ob diese mit der neuen Zeile identisch ist. Es ist übrigens durchaus wichtig, AnsiStrings zu verwenden und nicht etwa Strings. Dies würde der Compiler auch mit mehreren Implizite-Umwandlung-Warnungen quittieren.

Die NSS-Datei wird mittels Pfadangabe (hier die globale Konstante FNSSFilePath an einem bestimmten Platz gespeichert. Anstelle der Konstante sollte man sinnigerweise die Environment-Variable %SSLKEYLOGFILE% auswerten. Diese wird z.B. auch vom Firefox-Browser verwendet. Aber Vorsicht: Firefox und den eigenen Client nicht parallel laufen lassen, weil der Browser die Datei Write-Exclusive öffnet. Wir öffnen sie jedoch Shared-Read-Write, sodass wir zumindest keine anderen Anwendungen blockieren.

Schließlich muss Wireshark noch konfiguriert werden, die soeben erstellte NSS-Datei zur Entschlüsselung von SSL/TLS-Verbindungen zu nutzen.

Der oben schon erwähnte Bug in Indy 10 befand sich in der IdSSLOpenSSLHeaders.pas und wurde am 3. Dezember 2018 in den Indy-Quellen behoben. Daher ist es erforderlich, die Zeile Dec(PByte(LS3)); zu löschen, wenn man den Indy-10-Quellenstand vom 3.12.2018 oder später verwendet. Delphi 10.3 Rio wurde jedoch noch mit dem fehlerhaften Stand ausgeliefert.

Unterstützt wird aktuell SSLv1 bis SSLv3 sowie TLS 1.0 bis TLS 1.2. Zum jetzigen Zeitpunkt ist TLS 1.3 noch kein Thema, weil dafür größere Umbauten an Indy notwendig sind.

So, das wars dann auch schon. Happy SSL/TLS-Hacking!

Euer Cody
Ich mache grundsätzlich keine Screenshots. Schießen auf Bildschirme gibt nämlich hässliche Pixelfehler und schadet der Gesundheit vom Kollegen gegenüber.

Geändert von Codehunter ( 7. Mär 2019 um 10:34 Uhr)
 
Themen-Optionen Tutorial durchsuchen
Tutorial durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf