puerto - ¿Cómo deshabilito el respaldo SSL y uso solo TLS para conexiones salientes en.NET?(Mitigación de caniche)
puerto 8443 tomcat (6)
@watson
En formularios de Windows está disponible, en la parte superior de la clase poner
static void Main(string[] args)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
//other stuff here
}
dado que Windows es de un solo subproceso, es todo lo que necesita, en caso de que sea un servicio, debe colocarlo justo encima de la llamada al servicio (ya que no se sabe en qué subproceso estará).
using System.Security.Principal
También es necesario.
Estoy tratando de mitigar nuestra vulnerabilidad al ataque Poodle SSL 3.0 Fallback . Nuestros administradores ya han comenzado a deshabilitar SSL a favor de TLS para las conexiones entrantes a nuestros servidores. Y también hemos aconsejado a nuestro equipo que deshabilite SSL en sus navegadores web. Ahora estoy mirando nuestra base de código .NET, que inicia conexiones HTTPS con varios servicios a través de System.Net.HttpWebRequest . Creo que estas conexiones podrían ser vulnerables a un ataque MITM si permiten el retroceso de TLS a SSL. Esto es lo que he determinado hasta ahora. ¿Podría alguien verificar dos veces esto para verificar que tengo razón? Esta vulnerabilidad es completamente nueva, por lo que aún no he visto ninguna guía de Microsoft sobre cómo mitigarla en .NET:
-
Los protocolos permitidos para la clase System.Net.Security.SslStream, que sustenta la comunicación segura en .NET, se configuran globalmente para cada AppDomain a través de la propiedad System.Net.ServicePointManager.SecurityProtocol .
-
El valor predeterminado de esta propiedad en .NET 4.5 es
Ssl3 | Tls
Ssl3 | Tls
(aunque no puedo encontrar documentación para respaldar eso). SecurityProtocolType es una enumeración con el atributo Flags, por lo que es un OR bit a bit de esos dos valores. Puede verificar esto en su entorno con esta línea de código:Console.WriteLine (System.Net.ServicePointManager.SecurityProtocol.ToString ());
-
Esto debe cambiarse a solo
Tls
, o tal vezTls12
, antes de iniciar cualquier conexión en su aplicación:System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls;
-
Importante: dado que la propiedad admite varios indicadores bit a bit, supongo que SslStream no recurrirá automáticamente a otros protocolos no especificados durante el protocolo de enlace. De lo contrario, ¿cuál sería el punto de soportar múltiples banderas?
Actualización en TLS 1.0 vs 1.1 / 1.2:
Según el experto en seguridad de Google Adam Langley, más tarde se descubrió que TLS 1.0 era vulnerable a POODLE si no se implementaba correctamente , por lo que debería considerar mudarse a TLS 1.2 exclusivamente.
Encontré que la solución más simple es agregar dos entradas de registro de la siguiente manera (ejecute esto en un símbolo del sistema con privilegios 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
Estas entradas parecen afectar la forma en que .NET CLR elige un protocolo al realizar una conexión segura como cliente.
Hay más información sobre esta entrada de registro aquí:
https://docs.microsoft.com/en-us/security-updates/SecurityAdvisories/2015/2960358#suggested-actions
Esto no solo es más simple, sino suponiendo que funcione para su caso, mucho más robusto que una solución basada en código, que requiere que los desarrolladores rastreen el protocolo y el desarrollo y actualicen todo su código relevante. Con suerte, se pueden hacer cambios similares en el entorno para TLS 1.3 y más allá, siempre que .NET permanezca lo suficientemente tonto como para no elegir automáticamente el protocolo más alto disponible.
NOTA : aunque, de acuerdo con el artículo anterior, se supone que esto solo deshabilita RC4, y uno no pensaría que esto cambiaría si el cliente .NET puede usar TLS1.2 + o no, por alguna razón tiene esto efecto.
NOTA : Como señaló @Jordan Rieger en los comentarios, esta no es una solución para POODLE, ya que no deshabilita los protocolos más antiguos a: simplemente permite que el cliente trabaje con protocolos más nuevos, por ejemplo, cuando un servidor parcheado ha deshabilitado los más antiguos protocolos Sin embargo, con un ataque MITM, obviamente un servidor comprometido ofrecerá al cliente un protocolo más antiguo, que el cliente utilizará con gusto.
TODO : intente deshabilitar el uso del lado del cliente de TLS1.0 y TLS1.1 con estas entradas de registro, sin embargo, no sé si las bibliotecas de cliente http .NET respetan estas configuraciones o no:
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
Estamos haciendo lo mismo. Para admitir solo TLS 1.2 y ningún protocolo SSL, puede hacer esto:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
SecurityProtocolType.Tls es solo TLS 1.0, no todas las versiones de TLS.
Por otro lado: si desea verificar que su sitio no permita conexiones SSL, puede hacerlo aquí (no creo que esto se vea afectado por la configuración anterior, tuvimos que editar el registro para obligar a IIS a usar TLS para conexiones entrantes): https://www.ssllabs.com/ssltest/index.html
Para deshabilitar SSL 2.0 y 3.0 en IIS, consulte esta página: https://www.sslshopper.com/article-how-to-disable-ssl-2.0-in-iis-7.html
La respuesta de @Eddie Loeffen parece ser la respuesta más popular a esta pregunta, pero tiene algunos efectos negativos a largo plazo. Si revisa la página de documentación de System.Net.ServicePointManager.SecurityProtocol here la sección de comentarios implica que la fase de negociación solo debería abordar esto (y forzar el protocolo es una mala práctica porque en el futuro, TLS 1.2 también se verá comprometido). Sin embargo, no estaríamos buscando esta respuesta si lo hiciera.
Al investigar, parece que se requiere el protocolo de negociación ALPN para llegar a TLS1.2 en la fase de negociación. Tomamos eso como nuestro punto de partida y probamos versiones más nuevas del marco .Net para ver dónde comienza el soporte. Descubrimos que .Net 4.5.2 no admite la negociación con TLS 1.2, pero .Net 4.6 sí.
Entonces, aunque forzar TLS1.2 hará el trabajo ahora, le recomiendo que actualice a .Net 4.6 en su lugar. Como se trata de un problema de PCI DSS para junio de 2016, la ventana es corta, pero el nuevo marco es una mejor respuesta.
ACTUALIZACIÓN: A partir de los comentarios, construí esto:
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 el concepto, juntos SSL3 y TLS1.2 y ejecuté el código dirigido a un servidor que solo admite TLS 1.0 y TLS 1.2 (1.1 está deshabilitado). Con los protocolos or''d, parece conectarse bien. Si cambio a SSL3 y TLS 1.1, no se pudo conectar. Mi validación usa HttpWebRequest de System.Net y solo llama a GetResponse (). Por ejemplo, probé esto y fallé:
HttpWebRequest request = WebRequest.Create("https://www.contoso.com/my/web/resource") as HttpWebRequest;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls11;
request.GetResponse();
mientras esto funcionó:
HttpWebRequest request = WebRequest.Create("https://www.contoso.com/my/web/resource") as HttpWebRequest;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
request.GetResponse();
Esto tiene una ventaja sobre forzar TLS 1.2 en que, si se actualiza el marco .Net para que haya más entradas en Enum, el código las admitirá tal como están. Tiene una desventaja sobre el uso de .Net 4.6 ya que 4.6 usa ALPN y debería admitir nuevos protocolos si no se especifica ninguna restricción.
Edición 29/04/2019: Microsoft publicó este artículo en octubre pasado. Tiene una sinopsis bastante buena de su recomendación de cómo se debe hacer esto en las diversas versiones de .net framework.
Si tiene curiosidad sobre qué protocolos admite .NET, puede probar HttpClient en 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");
El resultado es condenatorio:
Su cliente está utilizando TLS 1.0, que es muy antiguo, posiblemente susceptible al ataque BEAST, y no tiene los mejores conjuntos de cifrado disponibles. Las adiciones como AES-GCM y SHA256 para reemplazar MD5-SHA-1 no están disponibles para un cliente TLS 1.0 ni para muchos conjuntos de cifrado más modernos.
Como Eddie explica anteriormente, puede habilitar mejores protocolos manualmente:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
No sé por qué usa protocolos incorrectos listos para usar. Esa parece una mala elección de configuración, lo que equivale a un importante error de seguridad (apuesto a que muchas aplicaciones no cambian el valor predeterminado). ¿Cómo podemos denunciarlo?
Tuve que convertir el número entero equivalente para evitar el hecho de que todavía estoy usando .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,
}
*/