SSLフォールバックを無効にし、.NETの送信接続にTLSのみを使用しますか?(プードル緩和)


106

Poodle SSL 3.0フォールバック攻撃に対する脆弱性を緩和しようとしています。私たちの管理者は、サーバーへのインバウンド接続のためにTLSを優先してSSLを無効にし始めています。また、ウェブブラウザでSSLを無効にするようチームにもアドバイスしました。現在、.NETコードベースを調べています。これは、System.Net.HttpWebRequestを介してさまざまなサービスとのHTTPS接続を開始します。これらの接続は、TLSからSSLへのフォールバックを許可する場合、MITM攻撃に対して脆弱になる可能性があると思います。これが私がこれまでに決定したことです。誰かがこれを再確認して、私が正しいことを確認できますか?この脆弱性はまったく新しいものであるため、.NETでこれを緩和する方法についてマイクロソフトからのガイダンスはまだ見ていません。

  1. .NETの安全な通信を支えるSystem.Net.Security.SslStreamクラスに許可されているプロトコルは、System.Net.ServicePointManager.SecurityProtocolプロパティを介して各AppDomainに対してグローバルに設定されます。

  2. .NET 4.5でのこのプロパティのデフォルト値はSsl3 | Tls(それを裏付けるドキュメントは見つかりませんが)です。SecurityProtocolTypeはFlags属性を持つ列挙型であるため、これら2つの値のビット単位のORです。次のコード行を使用して、環境でこれを確認できます。

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

  3. アプリで接続を開始する前にTls、これをに変更する必要がありTls12ます。

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

  4. 重要:プロパティは複数のビット単位のフラグをサポートしているため、SslStreamがハンドシェイク中に他の指定されていないプロトコルに自動的にフォールバックしないと想定してます。それ以外の場合、複数のフラグをサポートするポイントは何ですか?

TLS 1.0と1.1 / 1.2の更新:

Googleのセキュリティ専門家であるAdam Langley氏によると、正しく実装されていないとTLS 1.0が後でPOODLEに対して脆弱であることが判明したため、TLS 1.2のみに移行することを検討してください。

.NET Framework 4.7以降の更新:

以下のVon Lemongargle教授が言及しているように、.NET Frameworkのバージョン4.7以降では、デフォルトの設定でOSが最も安全なTLSプロトコルバージョンを選択できるため、このハックを使用する必要はありません。詳細については、.NET Frameworkでのトランスポート層セキュリティ(TLS)のベストプラクティスを参照してください。


1
上記のポイント2について:referencesource.microsoft.com/#System/net/System/Net/…SslProtocols "Default = Ssl3 | Tls"
Dai Bok

1
@Daiボク今オプションSystemDefaultされているデフォルトdocs.microsoft.com/en-us/dotnet/api/...
MarwaAhmad

@MarwaAhmadその場合、リンク内のソースコード参照はデフォルト(48 | 192)を反映しません。none(0)に設定すると、システムのデフォルトに戻るはずです。これは私ににおいがし、設定を誤る可能性があるため、変更を加える前にこれをテストするでしょう...そして、間違った.netフレームワークでプロトコルをオフにします...
Dai Bok

回答:


137

私たちは同じことをしています。TLS 1.2のみをサポートし、SSLプロトコルはサポートしないようにするには、次のようにします。

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

SecurityProtocolType.TlsはTLS 1.0のみであり、すべてのTLSバージョンではありません。

サイドとして:サイトがSSL接続を許可していないことを確認したい場合は、ここで確認できます(これは上記の設定の影響を受けないと思います。レジストリを編集してIISがTLSを使用するように強制する必要がありました。着信接続用):https : //www.ssllabs.com/ssltest/index.html

IISでSSL 2.0および3.0を無効にするには、次のページを参照してください。https//www.sslshopper.com/article-how-to-disable-ssl-2.0-in-iis-7.html


正しい。新しいTLSバージョンもサポートすることをお勧めします:将来性。
ジョーダンリーガー、2014年

1
そして、他の人のために、あなたが言及したレジストリの編集は、次の手順で行うこともできます:serverfault.com/a/637263/98656。Windows Server 2003から2012 R2では、プロトコルはHKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ SecurityProviders \ Schannel \ Protocolsにあるフラグによって制御されます。SSLv3を無効にするには、上記の場所に「SSL 3.0」というサブキーを作成し、その下に「Server」というサブキーを作成し、その下に「Enabled」というDWORD値を0に設定します。SSL2.0も無効にする必要があります。同じやり方で。
ジョーダンリーガー、2014年

4
@ScotterMonkey サーバーで実行されているカスタムコードからWebサービスまたはAPIに接続するなど、.NETコードから送信接続を開始する場合にのみ、System.Net.ServicePointManager.SecurityProtocolを設定する必要があります。単純なWebサイトのみを実行していて、ブラウザーからの着信接続のみを受け入れる場合は、レジストリの修正で十分です。
ジョーダンリーガー、2014年

7
注:表示されSecurityProtocolType.Tls11SecurityProtocolType.Tls12列挙値はASP.net 4.5以降でのみ使用できます。TLS 1.0が道に迷った場合、2.0で実行されている古いコードベースに対して何をしなければならないかわかりません。
サム

1
@AnishV送信SSL / TLS接続を開始するコードの前に、そのコード行をアプリの初期化に配置します。
ジョーダンリーガー

23

@Eddie Loeffenの回答は、この質問に対する最も人気のある回答のようですが、長期的な悪影響があります。ここでSystem.Net.ServicePointManager.SecurityProtocolのドキュメントページを確認すると、備考セクションは、ネゴシエーションフェーズでこれに対処する必要があることを示しています(将来、TLS 1.2も侵害されるため、プロトコルの強制は不適切です)。しかし、もしそうであったとしても、この答えを探すことはできません。

調査の結果、ALPNネゴシエーションプロトコルは、ネゴシエーションフェーズでTLS1.2に到達する必要があるようです。それを出発点として、.Netフレームワークの新しいバージョンを試して、サポートがどこから始まるかを確認しました。.Net 4.5.2はTLS 1.2へのネゴシエーションをサポートしていませんが、.Net 4.6はサポートしています。

そのため、TLS1.2を強制することで今のところ仕事は完了しますが、代わりに.Net 4.6にアップグレードすることをお勧めします。これは2016年6月のPCI DSSの問題であるため、ウィンドウは短いですが、新しいフレームワークの方が適切です。

更新:コメントから作業して、私はこれを構築しました:

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;
        }
    }

概念を検証するために、SSL3とTLS1.2を組み合わせて、TLS 1.0とTLS 1.2のみをサポートするサーバーを対象とするコードを実行しました(1.1は無効になっています)。or'dプロトコルでは、正常に接続しているようです。SSL3とTLS 1.1に変更すると、接続に失敗しました。私の検証では、System.NetからのHttpWebRequestを使用し、GetResponse()を呼び出します。たとえば、私はこれを試して失敗しました:

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

これがうまくいった間:

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

これには、TLS 1.2を強制するよりも利点があります。.NetフレームワークがアップグレードされてEnumにさらに多くのエントリがある場合、それらはそのままコードでサポートされます。4.6はALPNを使用し、制限が指定されていない場合は新しいプロトコルをサポートするという点で、.Net 4.6を使用する場合に比べて欠点があります。

編集4/29/2019-マイクロソフトはこの記事を昨年10月に公開しました。これは、.netフレームワークのさまざまなバージョンでこれをどのように行うべきかについての彼らの推奨のかなり良い概要を持っています。


3
面白い。ドキュメントページがMSDNの「.NET Framework (現在のバージョン)」への移行に伴って更新されたようであり、「このプロパティには、意図的にデフォルト値がリストされていない」と説明されています。おそらく、受け入れられる回答のより将来性のあるバージョンは、最初にプロパティをクエリして許可されたプロトコルのリストを取得し、次にアプリが安全でないと見なすもの(つまり、TLS 1.2未満のもの)を明示的に追加するのではなく削除します。あなたが安全だと思うもの。これにより、将来の新しいバージョンが除外されることはありません。
ジョーダンリーガー2016年

システムが生成するリストからプログラムがプロトコルを削除できるようにするのは良いことですが、現在のAPIでそれを行う方法がわかりません。唯一の選択肢は特定のプロトコルを強制することであると思われますが、なぜそれが望まれるのかはわかりません。残念ながら、ALPNサポートがなければ、TLS1.2接続を機能させる唯一の方法のようです。
Von Lemongargle教授、

1
すべてのSecurityProtocolType列挙型をループ処理し、ServicePointManager.SecurityProtocolフラグ列挙型に存在するものを確認します(これはすべての設定済みフラグの論理ORであり、それぞれをANDでテストできるため)、新しい削除したくないもののリスト。次に、それらを1つの列挙型に結合し、それにプロパティを設定します。
Jordan Rieger

私はあなたの列挙/ループコードを再読み込みしていましたが、それは間違っていると思います。| =論理演算子を使用すると、Tls12以上だけではなく、最初にプロパティに設定されたデフォルト値がすべてプロパティに含まれます。これを修正するには、SecurityProtocolType列挙型変数を値0で初期化し、その変数に対して| =ループを実行してから、それをServicePointManager.SecurityProtocolプロパティに割り当てます。
ジョーダンリーガー、2016年

7
.NETが可能な最高のプロトコルバージョンを自動的にネゴシエートしないということを他の誰かが気が狂っているか?
ラマン2017年

5

@ワトソン

Windowsフォームでは使用可能で、クラスの上部に配置

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

ウィンドウはシングルスレッドなので、必要なものはすべて、そのサービスの場合は、サービスの呼び出しの真上に置く必要があります(どのスレッドにいるかがわからないため)。

using System.Security.Principal 

も必要です。


5

.NETがサポートするプロトコルに興味がある場合は、https: //www.howsmyssl.com/でHttpClientを試すことができます。

// 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");

結果は酷いです:

クライアントはTLS 1.0を使用しています。これは非常に古く、おそらくBEAST攻撃の影響を受けやすく、利用可能な最良の暗号スイートがありません。AES-GCMやMD5-SHA-1を置き換えるSHA256などの追加機能は、TLS 1.0クライアントだけでなく、より多くの最新の暗号スイートでも使用できません。

Eddieが上で説明したように、手動でより良いプロトコルを有効にできます:

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

なぜそれがすぐに悪いプロトコルを使うのか分かりません。これは、不適切なセットアップの選択であり、重大なセキュリティバグに相当します(多くのアプリケーションがデフォルトを変更しないと思います)。どうすれば報告できますか?


5

私はまだ.NET 4.0を使用しているという事実を回避するために、同等の整数をキャストする必要がありました。

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

これは機能しますが、.NET 4.0はTLS 1.2をサポートしていませんが、.NET 4.5以降はTLS 1.2をサポートしています。したがって、.NET 4.0アプリケーションにこのコードを追加して(またはビット単位ORを実行してTLS 1.2ネゴシエーションのサポートを追加して)、それをビルドできますが、.NET 4.5以降にコードをデプロイする必要があります。blogs.perficient.com/microsoft/2016/04/tsl-1-2-and-net-support
rboy

これをまたを参照して、.NET 4.0のコードは、.NET 4.5と.NET 4.6を含む.NETの上位バージョンで問題なく動作しますstackoverflow.com/questions/33378902/...
rboy

整数キャストはTLS 1.2を送信するために機能しました。Tls12列挙値は存在しません
。NET4.0

2つの異なるポイント。私のコメントを見てください。値を設定できますが、ランタイムネットバージョンが4.0の場合は失敗します。このフラグを使用してコンパイルできますが、.NET 4.0の基本コンポーネントはTLS 1.2に必要な暗号をサポートしていないため、ランタイム.NETバージョンは4.5以上である必要があります(リンクを参照)
rboy

2
古い.NETランタイムバージョンには、TLS 1.2サポートを追加するためのいくつかのホットフィックスがあります。たとえば、support.microsoft.com / en-us / help / 3154518 /…、CZahrobskyは、修正プログラムも含まれているWin10秋のクリエーターの更新でこれを使用していた可能性があります。
サイレントトーン

1

最も簡単な解決策は、次のように2つのレジストリエントリを追加することです(これを管理者特権でコマンドプロンプトで実行します)。

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

これらのエントリは、.NET CLRがクライアントとして安全な接続を確立するときにプロトコルを選択する方法に影響を与えるようです。

このレジストリエントリの詳細については、次をご覧ください。

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

これは単純なだけでなく、それがあなたのケースで機能すると仮定すると、開発者がプロ​​トコルと開発を追跡し、関連するすべてのコードを更新する必要があるコードベースのソリューションよりもはるかに堅牢です。うまくいけば、.NETが利用可能な最高のプロトコルを自動的に選択しないほど十分に機能しないままである限り、TLS 1.3以降でも同様の環境変更を行うことができます。

:上記の記事によると、これはRC4を無効にすることだけを想定しており、.NETクライアントがTLS1.2 +の使用を許可されているかどうかを変更するとは考えられませんが、何らかの理由で効果。

:コメントで@Jordan Riegerが述べたように、これは古いプロトコルaを無効にしないため、POODLEの解決策ではありません。プロトコル。ただし、MITM攻撃では、侵害されたサーバーがクライアントに古いプロトコルを提供し、クライアントがそれを喜んで使用するようになります。

TODO:これらのレジストリエントリでTLS1.0およびTLS1.1のクライアント側の使用を無効にしてみてください。ただし、.NET httpクライアントライブラリがこれらの設定を尊重しているかどうかはわかりません。

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


コードの代替としてのレジストリ設定はすばらしいですが、これらの設定は実際にはTLS 1.0および1.1を無効にして、TLS 1.2以上を使用するクライアント接続のみを許可するのですか?リンクによると、それはTLSでRC4のみを無効にするようです。プードル攻撃はそれよりも広いと思います。
ジョーダンリーガー

@JordanRiegerこれらのレジストリエントリにより、.NETクライアントは、古いプロトコルが無効になっているサーバーに接続して、POODLEを軽減できます。これらがないと、サーバーが新しいプロトコルを要求している場合でも、.NETクライアントが古いプロトコルの使用を愚かに要求するため、クライアントはエラーをスローします。サーバーが古いプロトコルを使用した接続をまだ許可している場合、すべての賭けは無効になります。理論的には、古いプロトコル無効にする必要があります。サーバーでこれらを無効にできる同じレジストリエントリ(たとえば、nartac.com/Products/IISCrypto)がクライアントでも機能するのでしょうか。
ラマン

nartacが操作するレジストリエントリには、クライアントとして機能する場合とサーバーとして機能する場合の別々の設定があります。ただし、それらのインターフェイスが区別できるかどうかは覚えていません。このレジストリハックをサポートする.netのバージョンを知っていますか?
Von Lemongargle教授、2018年

@Ramanは私の質問のポイントですが、クライアントが制御していないサーバーに接続しているときにPOODLEの脆弱性を緩和することでした。この脆弱性により、MITM攻撃者はハッキング可能なプロトコルを古いTLSまたはSSLバージョンにダウングレードできます。RC4を無効にするだけでは不十分です。これらのレジストリ設定は特定の場合に役立つ可能性がありますが、私の質問のシナリオには役立ちません。
ジョーダンリーガー

1
@JordanRieger同意する。私はいくつかの追加の観察と考えでテキストを更新しました。
ラマン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.