Como faço para desativar o fallback SSL e usar somente TLS para conexões de saída no .NET? (Mitigação de poodle)

Estou tentando atenuar nossa vulnerabilidade ao ataque de Fallback SSL 3.0 do Poodle . Nossos administradores já começaram a desabilitar o SSL em favor do TLS para conexões de input para nossos servidores. Também aconselhamos nossa equipe a desativar o SSL em seus navegadores da web. Agora estou olhando para nossa base de código .NET, que inicia conexões HTTPS com vários serviços através de System.Net.HttpWebRequest . Acredito que essas conexões possam ser vulneráveis ​​a um ataque MITM, se permitirem fallback de TLS para SSL. Aqui está o que eu determinei até agora. Alguém poderia, por favor, verificar isso para verificar se estou certo? Esta vulnerabilidade é nova, então ainda não vi nenhuma orientação da Microsoft sobre como atenuá-la no .NET:

  1. Os protocolos permitidos para a class System.Net.Security.SslStream, que sustenta a comunicação segura no .NET, são definidos globalmente para cada AppDomain por meio da propriedade System.Net.ServicePointManager.SecurityProtocol .

  2. O valor padrão desta propriedade no .NET 4.5 é Ssl3 | Tls Ssl3 | Tls (embora eu não possa encontrar documentação para fazer o backup.) SecurityProtocolType é um enum com o atributo Flags, então é um OR bit a bit desses dois valores. Você pode verificar isso em seu ambiente com esta linha de código:

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

  3. Isso deve ser alterado para apenas Tls , ou talvez Tls12 , antes de iniciar qualquer conexão no seu aplicativo:

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

  4. Importante: Como a propriedade suporta vários sinalizadores bit a bit, presumo que o SslStream não fará fallback automaticamente para outros protocolos não especificados durante o handshake. Caso contrário, qual seria o sentido de suportar vários sinalizadores?

Atualização no TLS 1.0 vs 1.1 / 1.2:

De acordo com o especialista em segurança do Google, Adam Langley, o TLS 1.0 foi mais tarde considerado vulnerável ao POODLE se não implementado corretamente , portanto, você deve considerar migrar para o TLS 1.2 exclusivamente.

Nós estamos fazendo a mesma coisa. Para suportar apenas protocolos TLS 1.2 e não SSL, você pode fazer isso:

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

SecurityProtocolType.Tls é apenas TLS 1.0, nem todas as versões do TLS.

Como um lado: Se você quiser verificar se o seu site não permite conexões SSL, você pode fazê-lo aqui (eu não acho que isso será afetado pela configuração acima, tivemos que editar o registro para forçar o IIS a usar o TLS para conexões de input): https://www.ssllabs.com/ssltest/index.html

Para desativar o SSL 2.0 e 3.0 no IIS, consulte esta página: https://www.sslshopper.com/article-how-to-disable-ssl-2.0-in-iis-7.html

A resposta de @Eddie Loeffen parece ser a resposta mais popular para essa pergunta, mas tem alguns efeitos ruins a longo prazo. Se você revisar a página de documentação do System.Net.ServicePointManager.SecurityProtocol aqui, a seção de comentários implicará que a fase de negociação deve resolver isso (e forçar o protocolo é uma má prática, porque no futuro, o TLS 1.2 também será comprometido). No entanto, não estaríamos procurando por essa resposta se isso acontecesse.

Pesquisando, parece que o protocolo de negociação ALPN é necessário para chegar ao TLS1.2 na fase de negociação. Nós tomamos isso como nosso ponto de partida e tentamos versões mais novas da estrutura .Net para ver onde o suporte é iniciado. Descobrimos que o .Net 4.5.2 não suporta a negociação para o TLS 1.2, mas o .Net 4.6 possui.

Portanto, mesmo que forçar o TLS1.2 a concluir o trabalho agora, recomendo que você atualize para o .Net 4.6. Como esse é um problema do PCI DSS para junho de 2016, a janela é curta, mas o novo framework é uma resposta melhor.

ATUALIZAÇÃO: Trabalhando a partir dos comentários, eu construí isso:

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

Para validar o conceito, juntei o SSL3 e o TLS1.2 e executei o código de segmentação de um servidor que suporta apenas o TLS 1.0 e o TLS 1.2 (o 1.1 está desativado). Com os protocolos or’d, parece se conectar bem. Se eu mudar para SSL3 e TLS 1.1, isso falhou ao se conectar. Minha validação usa HttpWebRequest de System.Net e apenas chama GetResponse (). Por exemplo, eu tentei isso e falhei:

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

enquanto isso funcionou:

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

Isso tem uma vantagem sobre forçar o TLS 1.2 em que, se a estrutura .Net for atualizada para que haja mais inputs no Enum, elas serão suportadas pelo código como estão. Ele tem uma desvantagem sobre o uso apenas do .Net 4.6 em que o 4.6 usa o ALPN e deve suportar novos protocolos se nenhuma restrição for especificada.

@watson

Nos formulários do windows está disponível, no topo da class colocar

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

já que o windows é single threaded, é tudo que você precisa, no caso de ser um serviço que você precisa colocar logo acima da chamada para o serviço (já que não há como saber em qual thread você estará).

 using System.Security.Principal 

também é necessário.

Eu tive que lançar o inteiro equivalente para contornar o fato de que eu ainda estou usando o .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, } */ 

Se você está curioso para saber quais protocolos o .NET suporta, você pode testar o HttpClient em https://www.howsmyssl.com/

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

O resultado é condenatório:

Seu cliente está usando o TLS 1.0, que é muito antigo, possivelmente suscetível ao ataque BEAST, e não possui os melhores conjuntos de criptografia disponíveis nele. Adições como AES-GCM e SHA256 para replace o MD5-SHA-1 não estão disponíveis para um cliente TLS 1.0, assim como muitos outros pacotes de criptografia modernos.

Como Eddie explica acima, você pode ativar protocolos melhores manualmente:

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

Não sei por que usa protocolos ruins prontos para o uso. Isso parece uma escolha ruim de configuração, o que equivale a um grande bug de segurança (eu aposto que muitos aplicativos não mudam o padrão). Como podemos denunciá-lo?

Eu encontrei a solução mais simples é adicionar duas inputs de registro da seguinte forma (execute isso em um prompt de comando com privilégios de administrador):

 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 

Essas inputs parecem afetar como o .NET CLR escolhe um protocolo ao fazer uma conexão segura como um cliente.

Há mais informações sobre essa input do registro aqui:

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

Não só isso é mais simples, mas presumindo que funcione para o seu caso, muito mais robusto do que uma solução baseada em código, que exige que os desenvolvedores acompanhem o protocolo e o desenvolvimento e atualizem todo o código relevante. Esperançosamente, mudanças similares no ambiente podem ser feitas para o TLS 1.3 e além, enquanto o .NET permanece mudo o suficiente para não escolher automaticamente o maior protocolo disponível.

NOTA : Mesmo assim, de acordo com o artigo acima, isso só deveria desabilitar o RC4, e não se poderia pensar que isso mudaria se o cliente .NET tem permissão para usar o TLS1.2 + ou não, por alguma razão ele tem isso. efeito.

NOTA : Como observado por @Jordan Rieger nos comentários, isso não é uma solução para o POODLE, já que ele não desabilita os protocolos mais antigos – ele apenas permite que o cliente trabalhe com protocolos mais novos, por exemplo, quando um servidor com protocolos. No entanto, com um ataque MITM, obviamente, um servidor comprometido oferecerá ao cliente um protocolo antigo, que o cliente usará com alegria.

TODO : Tente desabilitar o uso de TLS1.0 e TLS1.1 no lado do cliente com essas inputs de registro, no entanto, não sei se as bibliotecas de clientes HTTP http respeitam essas configurações ou não:

http://www.google.com/support

http://www.google.com/support