Welche TLS-Version wurde ausgehandelt?

10

Ich habe meine App in .NET 4.7 ausgeführt. Standardmäßig wird versucht, TLS1.2 zu verwenden. Ist es möglich zu wissen, welche TLS-Version ausgehandelt wurde, wenn zum Beispiel eine HTTP-Anfrage wie folgt durchgeführt wurde?

%Vor%

Ich benötige diese Informationen nur für Protokollierungs- / Debugging-Zwecke. Daher ist es nicht wichtig, dass ich diese Informationen habe, bevor ich in den Anfragestream schreibe oder die Antwort erhalte. Ich möchte net Tracing-Protokolle für diese Informationen nicht analysieren, und ich möchte auch keine zweite Verbindung (mit SslStream oder ähnliches) erstellen.

    
Frederic 02.02.2018, 19:25
quelle

3 Antworten

4
  

UPDATE : Ich habe einen anderen möglichen Weg gefunden, das Protokoll zu verwenden   in diesen Verbindungen, aber es ist wahrscheinlich als Dokumentationsquelle nützlicher als als ein praktikabler Ersatz   Siehe das Update unten.

Sie können Reflection verwenden, um zum TlsStream->SslState->SslProtocol -Eigenschaftswert zu gelangen.
Diese Informationen können aus dem Stream extrahiert werden, der von HttpWebRequest.GetRequestStream() und HttpWebRequest.GetResponseStream() zurückgegeben wurde.

Die Validierung erfolgt in TlsValidationCallback , die aufgerufen wird, wenn die Anfrage mit request.GetRequestStream()

initialisiert wird %Vor%

Das RemoteCertificateValidationCallback enthält nützliche Informationen zu den verwendeten Sicherheitsprotokollen. (Siehe: TLS-Parameter (Transport Layer Security) und RFC 5246 ).
Die Arten der verwendeten Sicherheitsprotokolle können informativ genug sein, da jede Protokollversion eine Teilmenge von Hashing- und Verschlüsselungsalgorithmen unterstützt Tls 1.2, führt HMAC-SHA256 ein und veraltet die Codes IDEA und DES (alle Varianten sind in den verknüpften Dokumenten aufgelistet).

Hier habe ich ein OIDExtractor eingefügt, das die verwendeten Algorithmen auflistet.
Beachten Sie, dass sowohl TcpClient () als auch WebRequest () hierher kommen.

%Vor%

UPDATE 2:
Der secur32.dll - & gt; QueryContextAttributesW() method, ermöglicht die Abfrage des Connection Security Context eines initialisierten Streams.
using System.Net.Security;
using System.Reflection;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

    //(...)
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | 
                                           SecurityProtocolType.Tls | 
                                           SecurityProtocolType.Tls11 | 
                                           SecurityProtocolType.Tls12;
    ServicePointManager.ServerCertificateValidationCallback += TlsValidationCallback;

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(decodedUri);
    if (requestPayload.Length > 0)
    {
        using (Stream requestStream = request.GetRequestStream())
        {
            //Here the request stream is already validated
            SslProtocols SslProtocol = ExtractSslProtocol(requestStream);
            requestStream.Write(requestPayload, 0, requestPayload.Length);
        }
    }
    //(...)

private SslProtocols ExtractSslProtocol(Stream stream)
{
    BindingFlags bindingFlags = BindingFlags .Instance | BindingFlags .Public | 
                                BindingFlags .NonPublic | BindingFlags.Static;

    var _objConnection = stream.GetType().GetField("m_Connection", bindingFlags).GetValue(stream);
    var _objTlsStream = _objConnection.GetType().GetProperty("NetworkStream", bindingFlags).GetValue(_objConnection);
    var _objSslState = _objTlsStream.GetType().GetField("m_Worker", bindingFlags).GetValue(_objTlsStream);
    return (SslProtocols)_objSslState.GetType().GetProperty("SslProtocol", bindingFlags).GetValue(_objSslState);
}

Wie Sie der Dokumentation entnehmen können, gibt diese Methode eine void* buffer zurück, die auf eine SecPkgContext_ConnectionInfo -Struktur verweist:

%Vor%

Das Mitglied SchProtocols dwProtocol ist das SslProtocol.

Was ist der Haken?
Das TlsStream.Context.m_SecurityContext._handle , das auf den Connection Context-Handle verweist, ist nicht öffentlich.
Sie erhalten es also wiederum nur durch Reflexion oder durch die System.Net.Security.AuthenticatedStream abgeleiteten Klassen ( System.Net.Security.SslStream und System.Net.Security.NegotiateStream ), die von TcpClient.GetStream() zurückgegeben werden.

Leider kann der von WebRequest / WebResponse zurückgegebene Stream nicht in diese Klassen umgewandelt werden. Die Verbindungen und Streams-Typen werden nur durch nicht öffentliche Eigenschaften und Felder referenziert.

Ich veröffentliche die zusammengefügte Dokumentation, es hilft Ihnen vielleicht, einen anderen Pfad zu finden, um zu diesem Kontext-Handle zu gelangen.

Die Deklarationen, Strukturen, Aufzählungslisten befinden sich in QueryContextAttributesW (PASTEBIN) .

Microsoft TechNet
Authentifizierungsstrukturen

MSDN
Erstellen einer sicheren Verbindung mit Schannel p>

Informationen über Schannel-Verbindungen erhalten

Abfragen der Attribute eines Schannel-Kontexts

QueryContextAttributes (Schannel)

Codebasis (teilweise)

.NET-Referenzquelle

Internals.cs

interne Struktur SSPIHandle {}

interne enum ContextAttribute {}

UPDATE 1:
  

Ich habe in Ihrem Kommentar zu einer anderen Antwort gesehen, dass die Lösung verwendet    TcpClient() ist für Sie nicht akzeptabel. Ich verlasse es hier sowieso   Die Kommentare von Ben Voigt in diesem Artikel werden für alle anderen Interessierten nützlich sein. Außerdem sind 3 mögliche Lösungen besser als 2.

Einige Implementierungsdetails zum TcpClient ( ) SslStream Verwendung im angegebenen Kontext.

Wenn Protokollinformationen vor dem Initialisieren einer WebRequest erforderlich sind, kann eine TcpClient () - Verbindung im selben Kontext mit denselben Tools hergestellt werden, die für eine TLS-Verbindung erforderlich sind. Nämlich die ServicePointManager.SecurityProtocol Definieren der unterstützten Protokolle und der ServicePointManager.ServerCertificateValidationCallback um das Serverzertifikat zu validieren.

Sowohl TcpClient () als auch WebRequest können diese Einstellungen verwenden:
- Aktivieren Sie alle Protokolle und lassen Sie den Tls Handshake bestimmen, welcher verwendet wird.
- Definieren Sie einen RemoteCertificateValidationCallback() -Delegaten, um die X509Certificates zu validieren, die der Server in einem X509Chain übergibt.

In der Praxis ist der Tls-Handshake der gleiche, wenn ein TcpClient oder eine WebRequest-Verbindung hergestellt wird.
Dieser Ansatz lässt Sie wissen, welches Tls-Protokoll Ihre HttpWebRequest mit demselben Server aushandeln wird.

Richten Sie ein TcpClient() ein, um das SslStream zu empfangen und auszuwerten.
Das Flag checkCertificateRevocation wird auf false gesetzt, sodass der Prozess keine Zeit mit dem Aufrufen der Sperrliste verschwendet.
Der Callback für die Zertifikatsüberprüfung ist derselbe wie in ServicePointManager

angegeben %Vor%

Die TlsInfo -Klasse sammelt einige Informationen über die hergestellte sichere Verbindung:
- Tls-Protokollversion
- Verschlüsselungs- und Hash-Algorithmen - Das Serverzertifikat, das im SSL Handshake verwendet wird.

%Vor%     
Jimi 08.02.2018, 00:19
quelle
1

Die folgende Lösung ist sicherlich ein "Hack", da sie Reflektion verwendet, aber sie deckt derzeit die meisten Situationen ab, in denen Sie sich mit einer HttpWebRequest befinden könnten. Es wird null zurückgegeben, wenn die Tls-Version nicht ermittelt werden konnte. Es überprüft auch die Tls-Version in derselben Anfrage, bevor Sie etwas in den Anfrage-Stream geschrieben haben. Wenn der Stream Tls Handshake beim Aufruf der Methode noch nicht aufgetreten ist, wird er ausgelöst.

Ihre Beispielverwendung würde wie folgt aussehen:

%Vor%

Und die Methode:

%Vor%     
caesay 09.02.2018 13:35
quelle
0

Der einzige Weg, den ich herausfinden kann, ist die Verwendung von SslStream , um eine Testverbindung herzustellen, dann überprüfe SslProtocol Eigenschaft.

%Vor%

Ich habe überprüft, dass sslStream.SslProtocl immer gleich ist wie TlsStream.m_worker.SslProtocol , das von HttpWebRequest 's Connection verwendet wurde.

    
Alex.Wei 07.02.2018 11:32
quelle

Tags und Links