SSL-Fallback deaktivieren und nur TLS für ausgehende Verbindungen in .NET verwenden? (Pudelminderung)


106

Ich versuche, unsere Anfälligkeit für den Poodle SSL 3.0 Fallback- Angriff zu verringern . Unsere Administratoren haben bereits damit begonnen, SSL zugunsten von TLS für eingehende Verbindungen zu unseren Servern zu deaktivieren. Außerdem haben wir unserem Team empfohlen, SSL in den Webbrowsern zu deaktivieren. Ich betrachte jetzt unsere .NET-Codebasis, die HTTPS-Verbindungen mit verschiedenen Diensten über System.Net.HttpWebRequest initiiert . Ich glaube, dass diese Verbindungen für einen MITM-Angriff anfällig sein könnten, wenn sie einen Fallback von TLS auf SSL ermöglichen. Folgendes habe ich bisher festgestellt. Könnte jemand dies bitte noch einmal überprüfen, um zu überprüfen, ob ich Recht habe? Diese Sicherheitsanfälligkeit ist brandneu, daher habe ich noch keine Anleitung von Microsoft zur Minderung in .NET erhalten:

  1. Die zulässigen Protokolle für die System.Net.Security.SslStream-Klasse, die die sichere Kommunikation in .NET unterstützt, werden für jede AppDomain global über die System.Net.ServicePointManager.SecurityProtocol- Eigenschaft festgelegt.

  2. Der Standardwert dieser Eigenschaft in .NET 4.5 ist Ssl3 | Tls(obwohl ich keine Dokumentation zum Sichern finden kann). SecurityProtocolType ist eine Aufzählung mit dem Flags-Attribut, daher ist es ein bitweises ODER dieser beiden Werte. Sie können dies in Ihrer Umgebung mit folgender Codezeile überprüfen:

    Console.WriteLine (System.Net.ServicePointManager.SecurityProtocol.ToString ());

  3. Dies sollte nur geändert werden Tls, oder vielleicht Tls12, bevor Sie irgendwelche Verbindungen in Ihrer Anwendung initiieren:

    System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls;

  4. Wichtig: Da die Eigenschaft mehrere bitweise Flags unterstützt, gehe ich davon aus, dass der SslStream beim Handshake nicht automatisch auf andere nicht angegebene Protokolle zurückgreift . Was wäre sonst der Grund, mehrere Flags zu unterstützen?

Update auf TLS 1.0 vs 1.1 / 1.2:

Laut dem Google-Sicherheitsexperten Adam Langley wurde TLS 1.0 später als anfällig für POODLE eingestuft, wenn es nicht korrekt implementiert wurde. Daher sollten Sie in Betracht ziehen, ausschließlich auf TLS 1.2 umzusteigen .

Update für .NET Framework 4.7 und höher:

Wie von Prof. Von Lemongargle weiter unten angedeutet, muss dieser Hack ab Version 4.7 von .NET Framework nicht mehr verwendet werden, da das Betriebssystem mit der Standardeinstellung die sicherste TLS-Protokollversion auswählen kann. Siehe Transport Layer Security (TLS) Best Practices mit dem .NET Framework für weitere Informationen.


1
Zu Punkt 2 oben: siehe referencesource.microsoft.com/#System/net/System/Net/… SslProtocols "Default = Ssl3 | Tls"
Dai Bok

1
@Dai Bok Die Standardeinstellung ist jetzt die SystemDefault-Option docs.microsoft.com/en-us/dotnet/api/…
MarwaAhmad

@MarwaAhmad Wenn dies der Fall ist, spiegelt die Quellcode-Referenz in meinem Link nicht die Standardeinstellung wider (48 | 192). Wenn keine (0) festgelegt ist, sollte die Systemvorgabe wiederhergestellt werden. Das riecht für mich und ich würde es wahrscheinlich testen, bevor ich Änderungen vornehme, da dies zu Fehlkonfigurationen führen kann ... und Protokolle auf dem falschen .net-Framework ausschalten kann ...
Dai Bok

Antworten:


137

Wir machen das Gleiche. Um nur TLS 1.2 und keine SSL-Protokolle zu unterstützen, können Sie Folgendes tun:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

SecurityProtocolType.Tls ist nur TLS 1.0, nicht alle TLS-Versionen.

Nebenbei: Wenn Sie überprüfen möchten, ob Ihre Site keine SSL-Verbindungen zulässt, können Sie dies hier tun (ich glaube nicht, dass dies durch die obige Einstellung beeinflusst wird. Wir mussten die Registrierung bearbeiten, um IIS zur Verwendung von TLS zu zwingen für eingehende Verbindungen): https://www.ssllabs.com/ssltest/index.html

Informationen zum Deaktivieren von SSL 2.0 und 3.0 in IIS finden Sie auf dieser Seite: https://www.sslshopper.com/article-how-to-disable-ssl-2.0-in-iis-7.html


Richtig. Gute Idee, auch die neueren TLS-Versionen zu unterstützen: Zukunftssicherheit.
Jordan Rieger

1
Zum Wohle anderer kann die von Ihnen erwähnte Registrierungsbearbeitung auch mit den folgenden Schritten durchgeführt werden: serverfault.com/a/637263/98656 . In Windows Server 2003 bis 2012 R2 werden die Protokolle durch Flags unter HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ SecurityProviders \ Schannel \ Protocols gesteuert. Um SSLv3 zu deaktivieren, erstellen Sie an der oben genannten Stelle einen Unterschlüssel mit dem Namen 'SSL 3.0' und darunter einen Unterschlüssel mit dem Namen 'Server' und darunter einen DWORD-Wert mit dem Namen 'Enabled', der auf 0 gesetzt ist. Sie sollten auch SSL 2.0 deaktivieren auf die gleiche Weise.
Jordan Rieger

4
@ScotterMonkey Sie müssen System.Net.ServicePointManager.SecurityProtocol nur festlegen, wenn Sie ausgehende Verbindungen über .NET-Code initiieren , z. B. über benutzerdefinierten Code, der auf Ihrem Server ausgeführt wird, eine Verbindung zu einem Webdienst oder einer API herstellen. Wenn Sie nur eine einfache Website ausführen und nur eingehende Verbindungen von Browsern akzeptieren , reicht die Registrierungskorrektur aus.
Jordan Rieger

7
Hinweis: Es wird angezeigt SecurityProtocolType.Tls11und SecurityProtocolType.Tls12Aufzählungswerte sind nur in ASP.net 4.5 und höher verfügbar. Ich bin mir nicht sicher, was wir für ältere Codebasen unter 2.0 tun müssten, wenn TLS 1.0 auf der Strecke bleibt.
Sam

1
@AnishV Sie haben diese Codezeile in die Initialisierung Ihrer App eingefügt, vor jedem Code, der eine ausgehende SSL / TLS-Verbindung initiiert.
Jordan Rieger

23

Die Antwort von @Eddie Loeffen scheint die beliebteste Antwort auf diese Frage zu sein, hat aber einige schlechte Langzeiteffekte. Wenn Sie die Dokumentationsseite für System.Net.ServicePointManager.SecurityProtocol hier lesen , impliziert der Abschnitt "Bemerkungen", dass die Verhandlungsphase dies nur berücksichtigen sollte (und das Erzwingen des Protokolls ist eine schlechte Praxis, da TLS 1.2 in Zukunft ebenfalls gefährdet sein wird). Wir würden jedoch nicht nach dieser Antwort suchen, wenn dies der Fall wäre.

Nachforschungen zufolge scheint das ALPN-Verhandlungsprotokoll erforderlich zu sein, um in der Verhandlungsphase zu TLS1.2 zu gelangen. Wir haben dies als Ausgangspunkt genommen und neuere Versionen des .Net-Frameworks ausprobiert, um festzustellen, wo die Unterstützung beginnt. Wir haben festgestellt, dass .Net 4.5.2 die Aushandlung von TLS 1.2 nicht unterstützt, .Net 4.6 jedoch.

Obwohl das Erzwingen von TLS1.2 den Job jetzt erledigt, empfehle ich, stattdessen ein Upgrade auf .Net 4.6 durchzuführen. Da dies ein PCI-DSS-Problem für Juni 2016 ist, ist das Fenster kurz, aber das neue Framework ist eine bessere Antwort.

UPDATE: Ausgehend von den Kommentaren habe ich Folgendes erstellt:

ServicePointManager.SecurityProtocol = 0;    
foreach (SecurityProtocolType protocol in SecurityProtocolType.GetValues(typeof(SecurityProtocolType)))
    {
        switch (protocol)
        {
            case SecurityProtocolType.Ssl3:
            case SecurityProtocolType.Tls:
            case SecurityProtocolType.Tls11:
                break;
            default:
                ServicePointManager.SecurityProtocol |= protocol;
            break;
        }
    }

Um das Konzept zu validieren, habe ich SSL3 und TLS1.2 zusammen ausgeführt und den Code für einen Server ausgeführt, der nur TLS 1.0 und TLS 1.2 unterstützt (1.1 ist deaktiviert). Mit den or'd-Protokollen scheint es eine gute Verbindung zu geben. Wenn ich zu SSL3 und TLS 1.1 wechsle, konnte keine Verbindung hergestellt werden. Meine Validierung verwendet HttpWebRequest von System.Net und ruft nur GetResponse () auf. Zum Beispiel habe ich dies versucht und bin gescheitert:

        HttpWebRequest request = WebRequest.Create("https://www.contoso.com/my/web/resource") as HttpWebRequest;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls11;
        request.GetResponse();

während dies funktionierte:

        HttpWebRequest request = WebRequest.Create("https://www.contoso.com/my/web/resource") as HttpWebRequest;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
        request.GetResponse();

Dies hat gegenüber dem Erzwingen von TLS 1.2 den Vorteil, dass beim Aktualisieren des .NET-Frameworks, sodass mehr Einträge in der Aufzählung vorhanden sind, diese vom Code unverändert unterstützt werden. Es hat einen Nachteil gegenüber der Verwendung von .Net 4.6, da 4.6 ALPN verwendet und neue Protokolle unterstützen sollte, wenn keine Einschränkung angegeben ist.

Bearbeiten 29.04.2019 - Microsoft hat diesen Artikel im letzten Oktober veröffentlicht. Es enthält eine ziemlich gute Übersicht über die Empfehlungen, wie dies in den verschiedenen Versionen des .net-Frameworks erfolgen soll.


3
Interessant. Es sieht so aus, als ob die Dokumentationsseite zusammen mit dem MSDN-Wechsel zu ".NET Framework (aktuelle Version) " aktualisiert wurde und nun erklärt wird, dass "für diese Eigenschaft absichtlich kein Standardwert aufgeführt ist". Möglicherweise besteht eine zukunftssicherere Version der akzeptierten Antwort darin, zuerst die Eigenschaft abzufragen, um die Liste der zulässigen Protokolle abzurufen, und dann diejenigen zu entfernen, die Ihre App als unsicher erachtet (dh weniger als TLS 1.2), anstatt nur explizit die hinzuzufügen diejenigen, die Sie für sicher halten. Dies würde neue Versionen in der Zukunft nicht ausschließen.
Jordan Rieger

Es wäre gut, wenn das Programm Protokolle aus einer vom System generierten Liste entfernen könnte, aber ich sehe in der aktuellen API keine Möglichkeit, dies zu tun. Die einzige Möglichkeit scheint darin zu bestehen, das spezifische Protokoll zu erzwingen, was ich nicht verstehe, warum jemand dies wünschen würde. Ohne die ALPN-Unterstützung scheint dies leider die einzige Möglichkeit zu sein, eine TLS1.2-Verbindung zum Laufen zu bringen.
Prof. Von Lemongargle

1
Es sollte möglich sein, alle SecurityProtocolType-Enums zu durchlaufen, festzustellen, welche in der ServicePointManager.SecurityProtocol-Flags-Enum vorhanden sind (es ist ein logisches ODER aller gesetzten Flags, sodass Sie jedes mit einem UND testen können), und dann ein neues zu erstellen Liste von ihnen mit denen, die Sie nicht entfernen möchten. Kombinieren Sie diese dann zu einer Aufzählung und legen Sie die Eigenschaft damit fest.
Jordan Rieger

Ich habe gerade Ihren Enum / Loop-Code erneut gelesen und denke, dass er falsch ist. Der logische Operator | = führt dazu, dass die Eigenschaft alle Standardwerte enthält, die ursprünglich in der Eigenschaft festgelegt wurden, anstatt nur Tls12 und höher einzuschließen. Um dies zu beheben, müssen Sie eine SecurityProtocolType-Enum-Variable mit dem Wert 0 initialisieren, die | = -Schleife für diese Variable ausführen und sie anschließend der ServicePointManager.SecurityProtocol-Eigenschaft zuweisen.
Jordan Rieger

7
Findet es jemand anderes verrückt, dass .NET nicht automatisch die höchste Protokollversion aushandelt, zu der es fähig ist?!
Raman

5

@ Watson

Auf Windows-Formularen ist es verfügbar, ganz oben in der Klasse setzen

  static void Main(string[] args)
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
       //other stuff here
    }

Da Windows ein Single-Thread ist, ist es alles, was Sie brauchen. Für den Fall, dass es sich um einen Dienst handelt, müssen Sie ihn direkt über dem Aufruf des Dienstes platzieren (da nicht bekannt ist, auf welchem ​​Thread Sie sich befinden).

using System.Security.Principal 

wird auch benötigt.


5

Wenn Sie neugierig sind, welche Protokolle .NET unterstützt, können Sie HttpClient unter https://www.howsmyssl.com/ ausprobieren.

// set proxy if you need to
// WebRequest.DefaultWebProxy = new WebProxy("http://localhost:3128");

File.WriteAllText("howsmyssl-httpclient.html", new HttpClient().GetStringAsync("https://www.howsmyssl.com").Result);

// alternative using WebClient for older framework versions
// new WebClient().DownloadFile("https://www.howsmyssl.com/", "howsmyssl-webclient.html");

Das Ergebnis ist verdammt:

Ihr Client verwendet TLS 1.0, das sehr alt ist, möglicherweise für BEAST-Angriffe anfällig ist und nicht über die besten verfügbaren Chiffresuiten verfügt. Ergänzungen wie AES-GCM und SHA256 als Ersatz für MD5-SHA-1 sind für einen TLS 1.0-Client sowie für viele weitere moderne Cipher Suites nicht verfügbar.

Wie Eddie oben erklärt, können Sie bessere Protokolle manuell aktivieren:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11; 

Ich weiß nicht, warum es schlechte Protokolle verwendet. Das scheint eine schlechte Wahl für das Setup zu sein, was einem großen Sicherheitsfehler gleichkommt (ich wette, viele Anwendungen ändern die Standardeinstellung nicht). Wie können wir es melden?


5

Ich musste das Integer-Äquivalent umwandeln, um die Tatsache zu umgehen, dass ich immer noch .NET 4.0 verwende

System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
/* Note the property type  
   [System.Flags]
   public enum SecurityProtocolType
   {
     Ssl3 = 48,
     Tls = 192,
     Tls11 = 768,
     Tls12 = 3072,
   } 
*/

Dies funktioniert, aber .NET 4.0 unterstützt TLS 1.2 nicht, .NET 4.5 und höher unterstützen jedoch TLS 1.2. Sie können diesen Code also zu Ihrer .NET 4.0-Anwendung hinzufügen (oder ein bitweises ODER hinzufügen, um Unterstützung für die TLS 1.2-Aushandlung hinzuzufügen) und ihn erstellen. Sie müssen den Code jedoch unter .NET 4.5 oder höher bereitstellen. blogs.perficient.com/microsoft/2016/04/tsl-1-2-and-net-support
rboy


Die Ganzzahlumwandlung funktionierte für das Senden von TLS 1.2. Der Tls12 Enum Wert existiert einfach nicht in. NET 4.0
CZahrobsky

Zwei verschiedene Punkte. Siehe meinen Kommentar. Sie können den Wert eingeben, aber wenn Ihre Laufzeit-Net-Version 4.0 ist, schlägt dies fehl. Sie können mit diesem Flag kompilieren, aber Ihre .NET-Laufzeitversionen müssen mindestens 4.5 sein, da die Basiskomponenten unter .NET 4.0 die für TLS 1.2 erforderlichen Chiffren nicht unterstützen (siehe die Links)
rboy

2
Es gibt mehrere Hotfixes für ältere .NET-Laufzeitversionen, um TLS 1.2-Unterstützung hinzuzufügen. Beispiel: support.microsoft.com/en-us/help/3154518/… , CZahrobsky könnte dies auch für das Win10 Fall Creators-Update verwendet haben, das auch den Hotfix enthielt.
stiller Ton

1

Ich fand, dass die einfachste Lösung darin besteht, zwei Registrierungseinträge wie folgt hinzuzufügen (führen Sie dies an einer Eingabeaufforderung mit Administratorrechten aus):

reg add HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 /v SchUseStrongCrypto /t REG_DWORD /d 1 /reg:32

reg add HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 /v SchUseStrongCrypto /t REG_DWORD /d 1 /reg:64

Diese Einträge scheinen sich darauf auszuwirken, wie die .NET CLR ein Protokoll auswählt, wenn eine sichere Verbindung als Client hergestellt wird.

Weitere Informationen zu diesem Registrierungseintrag finden Sie hier:

https://docs.microsoft.com/en-us/security-updates/SecurityAdvisories/2015/2960358#suggested-actions

Dies ist nicht nur einfacher, sondern unter der Annahme, dass es für Ihren Fall funktioniert, weitaus robuster als eine codebasierte Lösung, bei der Entwickler das Protokoll und die Entwicklung verfolgen und den gesamten relevanten Code aktualisieren müssen. Hoffentlich können ähnliche Umgebungsänderungen für TLS 1.3 und höher vorgenommen werden, solange .NET dumm genug bleibt, um nicht automatisch das höchste verfügbare Protokoll auszuwählen.

HINWEIS : Auch wenn dies gemäß dem obigen Artikel nur RC4 deaktivieren soll, und man würde nicht glauben, dass sich dadurch ändern würde, ob der .NET-Client TLS1.2 + verwenden darf oder nicht, aus irgendeinem Grund hat er dies bewirken.

HINWEIS : Wie von @Jordan Rieger in den Kommentaren erwähnt, ist dies keine Lösung für POODLE, da die älteren Protokolle nicht deaktiviert werden. A - Der Client kann lediglich mit neueren Protokollen arbeiten, z. B. wenn ein gepatchter Server die älteren deaktiviert hat Protokolle. Bei einem MITM-Angriff bietet ein kompromittierter Server dem Client jedoch offensichtlich ein älteres Protokoll an, das der Client dann gerne verwendet.

TODO : Versuchen Sie, die clientseitige Verwendung von TLS1.0 und TLS1.1 mit diesen Registrierungseinträgen zu deaktivieren. Ich weiß jedoch nicht, ob die .NET http-Clientbibliotheken diese Einstellungen berücksichtigen oder nicht:

https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-10

https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-11


Registrierungseinstellungen als Alternative zu einem Code wären großartig, aber deaktivieren diese Einstellungen tatsächlich TLS 1.0 und 1.1, um nur Clientverbindungen mit TLS 1.2 und höher zuzulassen? Laut dem Link scheint es nur RC4 in TLS zu deaktivieren. Ich denke, der Pudelangriff ist breiter.
Jordan Rieger

@JordanRieger Mit diesen Registrierungseinträgen kann ein .NET-Client eine Verbindung zu einem Server herstellen, auf dem die älteren Protokolle deaktiviert sind, um POODLE zu verringern. Ohne diese wird der Client einen Fehler auslösen, da der .NET-Client dumm darauf besteht, ein älteres Protokoll zu verwenden, selbst wenn der Server nach einem neueren fragt. Alle Wetten sind deaktiviert, wenn Ihr Server weiterhin Verbindungen mit den älteren Protokollen zulässt. Theoretisch die älteren Protokolle sollten deaktiviert werden. Ich frage mich, ob dieselben Registrierungseinträge, mit denen diese auf dem Server deaktiviert werden können (z. B. nartac.com/Products/IISCrypto ), auch für den Client funktionieren würden.
Raman

In den von nartac manipulierten Registrierungseinträgen gibt es separate Einstellungen für (als) Client und (als) Server. Ich erinnere mich nicht, ob ihre Schnittstelle jedoch unterscheidet. Wissen Sie, welche .net-Versionen diesen Registrierungs-Hack unterstützen?
Prof. Von Lemongargle

@Raman Der Punkt meiner Frage war jedoch, die POODLE-Sicherheitsanfälligkeit zu verringern, wenn Ihr Client eine Verbindung zu einem Server herstellt, den Sie nicht kontrollieren. Die Sicherheitsanfälligkeit ermöglicht es einem MITM-Angreifer, das Protokoll auf eine ältere TLS- oder SSL-Version herunterzustufen, die gehackt werden kann. Es reicht nicht aus, nur RC4 zu deaktivieren. Diese Registrierungseinstellungen können in bestimmten Fällen nützlich sein, aber nicht das Szenario in meiner Frage.
Jordan Rieger

1
@ JordanRieger Einverstanden. Ich habe den Text mit einigen zusätzlichen Beobachtungen und Gedanken aktualisiert.
Raman
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.