SSL 폴백을 비활성화하고 .NET의 아웃 바운드 연결에 TLS 만 사용 하시겠습니까? (푸들 완화)


106

Poodle SSL 3.0 Fallback 공격에 대한 취약성을 완화하려고합니다 . 관리자는 이미 서버에 대한 인바운드 연결을 위해 TLS를 위해 SSL을 비활성화하기 시작했습니다. 그리고 우리 팀은 웹 브라우저에서 SSL을 비활성화하도록 조언했습니다. 이제 System.Net.HttpWebRequest를 통해 다양한 서비스와 HTTPS 연결을 시작하는 .NET 코드베이스를 살펴보고 있습니다. 이러한 연결이 TLS에서 SSL 로의 대체를 허용하는 경우 MITM 공격에 취약 할 수 있다고 생각합니다. 지금까지 제가 결정한 내용입니다. 누군가 내가 옳다는 것을 확인하기 위해 이것을 다시 확인해 주시겠습니까? 이 취약점은 완전히 새로운 것이므로 .NET에서 취약점을 완화하는 방법에 대한 Microsoft의 지침을 아직 보지 못했습니다.

  1. .NET의 보안 통신을 뒷받침하는 System.Net.Security.SslStream 클래스에 대해 허용되는 프로토콜은 System.Net.ServicePointManager.SecurityProtocol 속성을 통해 각 AppDomain에 대해 전역 적으로 설정 됩니다.

  2. .NET 4.5에서이 속성의 기본값은 Ssl3 | Tls(백업 할 문서를 찾을 수는 없지만)입니다. SecurityProtocolType은 Flags 속성이있는 열거 형이므로이 두 값 의 비트 단위 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 이상용 업데이트 :

아래 Prof 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 Bok 이제 기본값은 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 버전이 아닌 TLS 1.0입니다.

측면 : 사이트에서 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 버전도 지원하는 것이 좋습니다. 미래 보장.
Jordan Rieger 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으로 설정합니다. 또한 SSL 2.0을 비활성화해야합니다. 같은 방법으로.
Jordan Rieger 2014 년

4
@ScotterMonkey .NET 코드에서 아웃 바운드 연결을 시작하는 경우에만 System.Net.ServicePointManager.SecurityProtocol을 설정하면됩니다 ( 예 : 서버에서 실행중인 사용자 지정 코드에서 웹 서비스 또는 API에 연결). 간단한 웹 사이트 만 실행 중이고 브라우저에서 들어오는 연결 만 허용 하는 경우 레지스트리 수정으로 충분합니다.
Jordan Rieger 2014 년

7
참고 : 표시 SecurityProtocolType.Tls11되고 SecurityProtocolType.Tls12열거 형 값은 ASP.net 4.5 이상에서만 사용할 수 있습니다. TLS 1.0이 중단되면 2.0에서 실행되는 이전 코드베이스에 대해 우리가해야 할 일이 확실하지 않습니다.

1
@AnishV 아웃 바운드 SSL / TLS 연결을 시작하는 코드 앞에 앱 초기화에 해당 코드 줄을 넣습니다.
Jordan Rieger

23

@Eddie Loeffen의 답변이이 질문에 대한 가장 인기있는 답변 인 것 같지만 장기적으로 나쁜 영향을 미칩니다. 여기서 System.Net.ServicePointManager.SecurityProtocol에 대한 설명서 페이지를 검토하는 경우 비고 섹션은 협상 단계에서이 문제를 해결해야 함을 의미합니다 (향후 TLS 1.2도 손상 될 것이기 때문에 프로토콜을 강제하는 것은 좋지 않습니다). 그러나 만약 그렇다면 우리는이 대답을 찾지 않을 것입니다.

조사 결과 협상 단계에서 TLS1.2에 도달하려면 ALPN 협상 프로토콜이 필요한 것으로 보입니다. 이를 시작점으로 삼아 지원이 시작되는 위치를 확인하기 위해 .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();

이것은 Enum에 더 많은 항목이 있도록 .Net 프레임 워크가 업그레이드되면 코드에서 그대로 지원된다는 점에서 TLS 1.2를 강제하는 것보다 이점이 있습니다. 4.6은 ALPN을 사용하고 제한이 지정되지 않은 경우 새 프로토콜을 지원해야한다는 점에서 .Net 4.6을 사용하는 것보다 단점이 있습니다.

2019 년 4 월 29 일 편집-Microsoft는 지난 10 월 이 기사를 게시 했습니다 . 다양한 버전의 .net 프레임 워크에서이 작업을 수행하는 방법에 대한 권장 사항에 대한 꽤 좋은 개요가 있습니다.


3
흥미 롭군. MSDN이 ".NET Framework (현재 버전) " 로 이동함에 따라 설명서 페이지가 업데이트 된 것으로 보이며 이제 "의도적으로이 속성에 대한 기본값이 나열되지 않았습니다"라고 설명합니다. 허용되는 답변의 미래 보장 버전은 먼저 속성을 쿼리하여 허용 된 프로토콜 목록을 검색 한 다음 앱이 안전하지 않은 것으로 간주하는 프로토콜 (즉, TLS 1.2 미만)을 제거하는 것입니다. 당신이 안전하다고 생각하는 것들. 이것은 미래의 새 버전을 제외하지 않습니다.
Jordan Rieger

프로그램이 시스템이 생성하는 목록에서 프로토콜을 제거하도록 할 수 있으면 좋겠지 만 현재 API에서는이를 수행하는 방법이 보이지 않습니다. 유일한 옵션은 특정 프로토콜을 강제하는 것 같습니다. 왜 누군가가 원하는지 모르겠습니다. 안타깝게도 ALPN 지원이 없으면 TLS1.2 연결이 작동하도록하는 유일한 방법 인 것 같습니다.
Prof Von Lemongargle

1
모든 SecurityProtocolType 열거 형을 반복하고 ServicePointManager.SecurityProtocol 플래그 열거 형에 어떤 항목이 있는지 확인한 다음 (모든 설정된 플래그의 논리적 OR이므로 AND로 각각 테스트 할 수 있음) 새 항목을 빌드 할 수 있어야합니다. 제거하고 싶지 않은 항목이있는 목록입니다. 그런 다음 이들을 하나의 열거 형으로 결합하고 속성을 설정합니다.
Jordan Rieger

열거 형 / 루핑 코드를 다시 읽고 있었는데 잘못된 것 같습니다. | = 논리 연산자는 Tls12 이상 만 포함하지 않고 처음에 속성에 설정된 모든 기본값을 포함하는 속성을 생성합니다. 이 문제를 해결하려면 0 값으로 SecurityProtocolType 열거 형 변수를 초기화하고 해당 변수에 대해 | = 루프를 수행 한 다음 나중에 ServicePointManager.SecurityProtocol 속성에 할당해야합니다.
Jordan Rieger

7
다른 사람이 .NET이 가능한 가장 높은 프로토콜 버전을 자동으로 협상하지 않는다는 사실을 알고 있습니까?!
Raman

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을 사용하고 있습니다. TLS 1.0은 매우 오래되어 BEAST 공격에 취약 할 수 있으며 사용할 수있는 최상의 암호 그룹이 없습니다. MD5-SHA-1을 대체하기위한 AES-GCM 및 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 애플리케이션에 추가 (또는 TLS 1.2 협상 지원을 추가하기 위해 비트 OR 추가)하고 빌드 할 수 있지만 .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 열거 값은 그냥 존재하지 않는 NET 4.0.
CZahrobsky

두 가지 다른 점. 내 의견을 참조하십시오. 값을 입력 할 수 있지만 런타임 Net 버전이 4.0이면 실패합니다. 이 플래그로 컴파일 할 수 있지만 .NET 4.0의 기본 구성 요소가 TLS 1.2에 필요한 암호를 지원하지 않으므로 런타임 .NET 버전은 4.5 이상이어야합니다 (링크 참조)
rboy

2
TLS 1.2 지원을 추가하기위한 이전 .NET 런타임 버전에 대한 몇 가지 핫픽스가 있습니다. 예를 들어 support.microsoft.com/en-us/help/3154518/… , CZahrobsky는 핫픽스도 포함 된 Win10 가을 크리에이터 업데이트에서도이 기능을 사용할 수있었습니다.
조용한 톤

1

가장 간단한 해결책은 다음과 같이 두 개의 레지스트리 항목을 추가하는 것입니다 (관리자 권한으로 명령 프롬프트에서 실행).

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가 언급했듯이 이것은 이전 프로토콜을 비활성화 하지 않기 때문에 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.2 이상을 사용하는 클라이언트 연결 만 허용하기 위해 TLS 1.0 및 1.1을 비활성화합니까? 링크에 따르면 TLS에서 RC4 만 비활성화하는 것으로 보입니다. 푸들 공격은 그것보다 더 광범위하다고 생각합니다.
Jordan Rieger

@JordanRieger 이러한 레지스트리 항목을 사용하면 .NET 클라이언트가 POODLE을 완화하기 위해 이전 프로토콜이 비활성화 된 서버에 연결할 수 있습니다. 이것들이 없으면 .NET 클라이언트가 서버가 새로운 프로토콜을 요구할 때에도 이전 프로토콜을 사용하도록 어리석게 주장하기 때문에 클라이언트는 오류를 던질 것입니다. 서버가 이전 프로토콜을 사용하는 연결을 계속 허용하면 모든 베팅이 해제됩니다. 이론적으로 이전 프로토콜 비활성화 되어야 합니다. 서버 (예 : nartac.com/Products/IISCrypto ) 에서 이러한 항목을 비활성화 할 수있는 동일한 레지스트리 항목이 클라이언트에서도 작동 하는지 궁금합니다 .
Raman

nartac이 조작하는 레지스트리 항목에는 클라이언트 (역할을 할 때)와 서버 (역할을 할 때)에 대한 별도의 설정이 있습니다. 그러나 그들의 인터페이스가 구별되는지 기억하지 못합니다. 이 레지스트리 해킹을 지원하는 .net 버전을 알고 있습니까?
Prof Von Lemongargle

@Raman이 내 질문의 요점은 클라이언트가 제어하지 않는 서버에 연결할 때 POODLE 취약점을 완화하는 것입니다. 취약점으로 인해 MITM 공격자가 프로토콜을 해킹 될 수있는 이전 TLS 또는 SSL 버전으로 다운 그레이드 할 수 있습니다. RC4를 비활성화하는 것만으로는 충분하지 않습니다. 이러한 레지스트리 설정은 특정 경우에 유용 할 수 있지만 내 질문의 시나리오는 아닙니다.
Jordan Rieger

1
@JordanRieger 동의합니다. 나는 몇 가지 추가 관찰과 생각으로 텍스트를 업데이트했습니다.
Raman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.